9128 cw(1onbld) should be able to run multiple shadows
[unleashed.git] / usr / src / common / ctf / ctf_types.c
blobab1b9ff14bd245253631137bc831f70dfdab1099
1 /*
2 * CDDL HEADER START
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.
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]
20 * CDDL HEADER END
24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 #include <ctf_impl.h>
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)
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);
40 } else {
41 size = tp->ctt_size;
42 increment = sizeof (ctf_stype_t);
45 if (sizep)
46 *sizep = size;
47 if (incrementp)
48 *incrementp = increment;
50 return (size);
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.
57 int
58 ctf_member_iter(ctf_file_t *fp, ctf_id_t type, ctf_member_f *func, void *arg)
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;
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,
85 arg)) != 0)
86 return (rc);
89 } else {
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)
97 return (rc);
101 return (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;
114 ssize_t increment;
115 uint_t n;
116 int rc;
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)
134 return (rc);
137 return (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)
154 return (rc);
157 return (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.
167 ctf_id_t
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)) {
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));
185 prev = type;
186 type = tp->ctt_type;
187 break;
188 default:
189 return (type);
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.
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)
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;
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) {
217 ctf_decl_fini(&cd);
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, " ");
248 if (lp == prec) {
249 ctf_decl_sprintf(&cd, "(");
250 lp = -1;
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;
300 k = cdp->cd_kind;
303 if (rp == prec)
304 ctf_decl_sprintf(&cd, ")");
307 if (cd.cd_len >= len)
308 (void) ctf_set_errno(fp, ECTF_NAMELEN);
310 ctf_decl_fini(&cd);
311 return (cd.cd_len);
314 ssize_t
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.
324 char *
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);
331 char *
332 ctf_type_qname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
333 const char *qname)
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.
344 ssize_t
345 ctf_type_size(ctf_file_t *fp, ctf_id_t type)
347 const ctf_type_t *tp;
348 ssize_t size;
349 ctf_arinfo_t ar;
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)) {
358 case CTF_K_POINTER:
359 return (fp->ctf_dmodel->ctd_pointer);
361 case CTF_K_FUNCTION:
362 return (0); /* function size is only known by symtab */
364 case CTF_K_ENUM:
365 return (fp->ctf_dmodel->ctd_int);
367 case CTF_K_ARRAY:
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)
376 return (size);
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);
384 default:
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.
393 ssize_t
394 ctf_type_align(ctf_file_t *fp, ctf_id_t type)
396 const ctf_type_t *tp;
397 ctf_arinfo_t r;
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)) {
406 case CTF_K_POINTER:
407 case CTF_K_FUNCTION:
408 return (fp->ctf_dmodel->ctd_pointer);
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));
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;
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);
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);
443 return (align);
446 case CTF_K_ENUM:
447 return (fp->ctf_dmodel->ctd_int);
449 default:
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.
472 ctf_id_t
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)) {
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));
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.
500 ctf_id_t
501 ctf_type_pointer(ctf_file_t *fp, ctf_id_t type)
503 ctf_file_t *ofp = fp;
504 ctf_id_t ntype;
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;
532 ssize_t increment;
533 uint_t data;
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)) {
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));
557 return (0);
561 ctf_type_cmp(ctf_file_t *lfp, ctf_id_t ltype, ctf_file_t *rfp, ctf_id_t rtype)
563 int rval;
565 if (ltype < rtype)
566 rval = -1;
567 else if (ltype > rtype)
568 rval = 1;
569 else
570 rval = 0;
572 if (lfp == rfp)
573 return (rval);
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;
581 if (lfp < rfp)
582 return (-1);
584 if (lfp > rfp)
585 return (1);
587 return (rval);
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;
602 ctf_arinfo_t la, ra;
603 uint_t lkind, rkind;
605 if (ctf_type_cmp(lfp, ltype, rfp, rtype) == 0)
606 return (1);
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)
619 return (0);
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 */
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,
652 ctf_membinfo_t *mip)
654 ctf_file_t *ofp = fp;
655 const ctf_type_t *tp;
656 ssize_t size, increment;
657 uint_t kind, n;
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;
679 return (0);
682 } else {
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);
690 return (0);
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;
707 ssize_t increment;
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;
722 return (0);
726 * Convert the specified value to the corresponding enum member name, if a
727 * matching name can be found. Otherwise NULL is returned.
729 const char *
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;
735 ssize_t increment;
736 uint_t n;
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);
746 return (NULL);
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);
759 return (NULL);
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;
773 uint_t n;
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);
783 return (CTF_ERR);
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) {
792 if (valp != NULL)
793 *valp = ep->cte_value;
794 return (0);
798 (void) ctf_set_errno(ofp, ECTF_NOENUMNAM);
799 return (CTF_ERR);
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.
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)
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;
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)
826 return (rc);
828 kind = LCTF_INFO_KIND(fp, tp->ctt_info);
830 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
831 return (0);
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)
843 return (rc);
846 } else {
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),
854 depth + 1)) != 0)
855 return (rc);
859 return (0);
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));