]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - cddl/contrib/opensolaris/common/ctf/ctf_types.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / cddl / contrib / opensolaris / common / ctf / ctf_types.c
1 /*
2  * CDDL HEADER START
3  *
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.
8  *
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.
13  *
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]
19  *
20  * CDDL HEADER END
21  */
22
23 /*
24  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27
28 #include <ctf_impl.h>
29
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)
33 {
34         ssize_t size, increment;
35
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);
43         }
44
45         if (sizep)
46                 *sizep = size;
47         if (incrementp)
48                 *incrementp = increment;
49
50         return (size);
51 }
52
53 /*
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.
56  */
57 int
58 ctf_member_iter(ctf_file_t *fp, ctf_id_t type, ctf_member_f *func, void *arg)
59 {
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;
65
66         if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
67                 return (CTF_ERR); /* errno is set for us */
68
69         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
70                 return (CTF_ERR); /* errno is set for us */
71
72         (void) ctf_get_ctt_size(fp, tp, &size, &increment);
73         kind = LCTF_INFO_KIND(fp, tp->ctt_info);
74
75         if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
76                 return (ctf_set_errno(ofp, ECTF_NOTSOU));
77
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);
81
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);
87                 }
88
89         } else {
90                 const ctf_lmember_t *lmp = (const ctf_lmember_t *)
91                     ((uintptr_t)tp + increment);
92
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);
98                 }
99         }
100
101         return (0);
102 }
103
104 /*
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.
107  */
108 int
109 ctf_enum_iter(ctf_file_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg)
110 {
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;
117
118         if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
119                 return (CTF_ERR); /* errno is set for us */
120
121         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
122                 return (CTF_ERR); /* errno is set for us */
123
124         if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ENUM)
125                 return (ctf_set_errno(ofp, ECTF_NOTENUM));
126
127         (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
128
129         ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
130
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);
135         }
136
137         return (0);
138 }
139
140 /*
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.
143  */
144 int
145 ctf_type_iter(ctf_file_t *fp, ctf_type_f *func, void *arg)
146 {
147         ctf_id_t id, max = fp->ctf_typemax;
148         int rc, child = (fp->ctf_flags & LCTF_CHILD);
149
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);
155         }
156
157         return (0);
158 }
159
160 /*
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.
166  */
167 ctf_id_t
168 ctf_type_resolve(ctf_file_t *fp, ctf_id_t type)
169 {
170         ctf_id_t prev = type, otype = type;
171         ctf_file_t *ofp = fp;
172         const ctf_type_t *tp;
173
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));
184                         }
185                         prev = type;
186                         type = tp->ctt_type;
187                         break;
188                 default:
189                         return (type);
190                 }
191         }
192
193         return (CTF_ERR); /* errno is set for us */
194 }
195
196 /*
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.
199  */
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)
203 {
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;
209
210         if (fp == NULL && type == CTF_ERR)
211                 return (-1); /* simplify caller code by permitting CTF_ERR */
212
213         ctf_decl_init(&cd, buf, len);
214         ctf_decl_push(&cd, fp, type);
215
216         if (cd.cd_err != 0) {
217                 ctf_decl_fini(&cd);
218                 return (ctf_set_errno(fp, cd.cd_err));
219         }
220
221         /*
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 (*[])().
227          */
228         ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER;
229         arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY;
230
231         rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1;
232         lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1;
233
234         k = CTF_K_POINTER; /* avoid leading whitespace (see below) */
235
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)) {
239
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);
244
245                         if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
246                                 ctf_decl_sprintf(&cd, " ");
247
248                         if (lp == prec) {
249                                 ctf_decl_sprintf(&cd, "(");
250                                 lp = -1;
251                         }
252
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;
298                         }
299
300                         k = cdp->cd_kind;
301                 }
302
303                 if (rp == prec)
304                         ctf_decl_sprintf(&cd, ")");
305         }
306
307         if (cd.cd_len >= len)
308                 (void) ctf_set_errno(fp, ECTF_NAMELEN);
309
310         ctf_decl_fini(&cd);
311         return (cd.cd_len);
312 }
313
314 ssize_t
315 ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
316 {
317         return (ctf_type_qlname(fp, type, buf, len, NULL));
318 }
319
320 /*
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.
323  */
324 char *
325 ctf_type_name(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
326 {
327         ssize_t rv = ctf_type_qlname(fp, type, buf, len, NULL);
328         return (rv >= 0 && rv < len ? buf : NULL);
329 }
330
331 char *
332 ctf_type_qname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
333     const char *qname)
334 {
335         ssize_t rv = ctf_type_qlname(fp, type, buf, len, qname);
336         return (rv >= 0 && rv < len ? buf : NULL);
337 }
338
339
340 /*
341  * Resolve the type down to a base type node, and then return the size
342  * of the type storage in bytes.
343  */
344 ssize_t
345 ctf_type_size(ctf_file_t *fp, ctf_id_t type)
346 {
347         const ctf_type_t *tp;
348         ssize_t size;
349         ctf_arinfo_t ar;
350
351         if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
352                 return (-1); /* errno is set for us */
353
354         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
355                 return (-1); /* errno is set for us */
356
357         switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {
358         case CTF_K_POINTER:
359                 return (fp->ctf_dmodel->ctd_pointer);
360
361         case CTF_K_FUNCTION:
362                 return (0); /* function size is only known by symtab */
363
364         case CTF_K_ENUM:
365                 return (fp->ctf_dmodel->ctd_int);
366
367         case CTF_K_ARRAY:
368                 /*
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.
374                  */
375                 if ((size = ctf_get_ctt_size(fp, tp, NULL, NULL)) > 0)
376                         return (size);
377
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 */
381
382                 return (size * ar.ctr_nelems);
383
384         default:
385                 return (ctf_get_ctt_size(fp, tp, NULL, NULL));
386         }
387 }
388
389 /*
390  * Resolve the type down to a base type node, and then return the alignment
391  * needed for the type storage in bytes.
392  */
393 ssize_t
394 ctf_type_align(ctf_file_t *fp, ctf_id_t type)
395 {
396         const ctf_type_t *tp;
397         ctf_arinfo_t r;
398
399         if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
400                 return (-1); /* errno is set for us */
401
402         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
403                 return (-1); /* errno is set for us */
404
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);
409
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));
414
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;
421
422                 (void) ctf_get_ctt_size(fp, tp, &size, &increment);
423                 vmp = (uchar_t *)tp + increment;
424
425                 if (LCTF_INFO_KIND(fp, tp->ctt_info) == CTF_K_STRUCT)
426                         n = MIN(n, 1); /* only use first member for structs */
427
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);
434                         }
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);
440                         }
441                 }
442
443                 return (align);
444         }
445
446         case CTF_K_ENUM:
447                 return (fp->ctf_dmodel->ctd_int);
448
449         default:
450                 return (ctf_get_ctt_size(fp, tp, NULL, NULL));
451         }
452 }
453
454 /*
455  * Return the kind (CTF_K_* constant) for the specified type ID.
456  */
457 int
458 ctf_type_kind(ctf_file_t *fp, ctf_id_t type)
459 {
460         const ctf_type_t *tp;
461
462         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
463                 return (CTF_ERR); /* errno is set for us */
464
465         return (LCTF_INFO_KIND(fp, tp->ctt_info));
466 }
467
468 /*
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.
471  */
472 ctf_id_t
473 ctf_type_reference(ctf_file_t *fp, ctf_id_t type)
474 {
475         ctf_file_t *ofp = fp;
476         const ctf_type_t *tp;
477
478         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
479                 return (CTF_ERR); /* errno is set for us */
480
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));
490         }
491 }
492
493 /*
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.
499  */
500 ctf_id_t
501 ctf_type_pointer(ctf_file_t *fp, ctf_id_t type)
502 {
503         ctf_file_t *ofp = fp;
504         ctf_id_t ntype;
505
506         if (ctf_lookup_by_id(&fp, type) == NULL)
507                 return (CTF_ERR); /* errno is set for us */
508
509         if ((ntype = fp->ctf_ptrtab[CTF_TYPE_TO_INDEX(type)]) != 0)
510                 return (CTF_INDEX_TO_TYPE(ntype, (fp->ctf_flags & LCTF_CHILD)));
511
512         if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
513                 return (ctf_set_errno(ofp, ECTF_NOTYPE));
514
515         if (ctf_lookup_by_id(&fp, type) == NULL)
516                 return (ctf_set_errno(ofp, ECTF_NOTYPE));
517
518         if ((ntype = fp->ctf_ptrtab[CTF_TYPE_TO_INDEX(type)]) != 0)
519                 return (CTF_INDEX_TO_TYPE(ntype, (fp->ctf_flags & LCTF_CHILD)));
520
521         return (ctf_set_errno(ofp, ECTF_NOTYPE));
522 }
523
524 /*
525  * Return the encoding for the specified INTEGER or FLOAT.
526  */
527 int
528 ctf_type_encoding(ctf_file_t *fp, ctf_id_t type, ctf_encoding_t *ep)
529 {
530         ctf_file_t *ofp = fp;
531         const ctf_type_t *tp;
532         ssize_t increment;
533         uint_t data;
534
535         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
536                 return (CTF_ERR); /* errno is set for us */
537
538         (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
539
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));
555         }
556
557         return (0);
558 }
559
560 int
561 ctf_type_cmp(ctf_file_t *lfp, ctf_id_t ltype, ctf_file_t *rfp, ctf_id_t rtype)
562 {
563         int rval;
564
565         if (ltype < rtype)
566                 rval = -1;
567         else if (ltype > rtype)
568                 rval = 1;
569         else
570                 rval = 0;
571
572         if (lfp == rfp)
573                 return (rval);
574
575         if (CTF_TYPE_ISPARENT(ltype) && lfp->ctf_parent != NULL)
576                 lfp = lfp->ctf_parent;
577
578         if (CTF_TYPE_ISPARENT(rtype) && rfp->ctf_parent != NULL)
579                 rfp = rfp->ctf_parent;
580
581         if (lfp < rfp)
582                 return (-1);
583
584         if (lfp > rfp)
585                 return (1);
586
587         return (rval);
588 }
589
590 /*
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.
595  */
596 int
597 ctf_type_compat(ctf_file_t *lfp, ctf_id_t ltype,
598     ctf_file_t *rfp, ctf_id_t rtype)
599 {
600         const ctf_type_t *ltp, *rtp;
601         ctf_encoding_t le, re;
602         ctf_arinfo_t la, ra;
603         uint_t lkind, rkind;
604
605         if (ctf_type_cmp(lfp, ltype, rfp, rtype) == 0)
606                 return (1);
607
608         ltype = ctf_type_resolve(lfp, ltype);
609         lkind = ctf_type_kind(lfp, ltype);
610
611         rtype = ctf_type_resolve(rfp, rtype);
612         rkind = ctf_type_kind(rfp, rtype);
613
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);
620
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 */
644         }
645 }
646
647 /*
648  * Return the type and offset for a given member of a STRUCT or UNION.
649  */
650 int
651 ctf_member_info(ctf_file_t *fp, ctf_id_t type, const char *name,
652     ctf_membinfo_t *mip)
653 {
654         ctf_file_t *ofp = fp;
655         const ctf_type_t *tp;
656         ssize_t size, increment;
657         uint_t kind, n;
658
659         if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
660                 return (CTF_ERR); /* errno is set for us */
661
662         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
663                 return (CTF_ERR); /* errno is set for us */
664
665         (void) ctf_get_ctt_size(fp, tp, &size, &increment);
666         kind = LCTF_INFO_KIND(fp, tp->ctt_info);
667
668         if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
669                 return (ctf_set_errno(ofp, ECTF_NOTSOU));
670
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);
674
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);
680                         }
681                 }
682         } else {
683                 const ctf_lmember_t *lmp = (const ctf_lmember_t *)
684                     ((uintptr_t)tp + increment);
685
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);
691                         }
692                 }
693         }
694
695         return (ctf_set_errno(ofp, ECTF_NOMEMBNAM));
696 }
697
698 /*
699  * Return the array type, index, and size information for the specified ARRAY.
700  */
701 int
702 ctf_array_info(ctf_file_t *fp, ctf_id_t type, ctf_arinfo_t *arp)
703 {
704         ctf_file_t *ofp = fp;
705         const ctf_type_t *tp;
706         const ctf_array_t *ap;
707         ssize_t increment;
708
709         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
710                 return (CTF_ERR); /* errno is set for us */
711
712         if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ARRAY)
713                 return (ctf_set_errno(ofp, ECTF_NOTARRAY));
714
715         (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
716
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;
721
722         return (0);
723 }
724
725 /*
726  * Convert the specified value to the corresponding enum member name, if a
727  * matching name can be found.  Otherwise NULL is returned.
728  */
729 const char *
730 ctf_enum_name(ctf_file_t *fp, ctf_id_t type, int value)
731 {
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;
737
738         if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
739                 return (NULL); /* errno is set for us */
740
741         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
742                 return (NULL); /* errno is set for us */
743
744         if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ENUM) {
745                 (void) ctf_set_errno(ofp, ECTF_NOTENUM);
746                 return (NULL);
747         }
748
749         (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
750
751         ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
752
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));
756         }
757
758         (void) ctf_set_errno(ofp, ECTF_NOENUMNAM);
759         return (NULL);
760 }
761
762 /*
763  * Convert the specified enum tag name to the corresponding value, if a
764  * matching name can be found.  Otherwise CTF_ERR is returned.
765  */
766 int
767 ctf_enum_value(ctf_file_t *fp, ctf_id_t type, const char *name, int *valp)
768 {
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;
774
775         if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
776                 return (CTF_ERR); /* errno is set for us */
777
778         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
779                 return (CTF_ERR); /* errno is set for us */
780
781         if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ENUM) {
782                 (void) ctf_set_errno(ofp, ECTF_NOTENUM);
783                 return (CTF_ERR);
784         }
785
786         (void) ctf_get_ctt_size(fp, tp, &size, &increment);
787
788         ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
789
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);
795                 }
796         }
797
798         (void) ctf_set_errno(ofp, ECTF_NOENUMNAM);
799         return (CTF_ERR);
800 }
801
802 /*
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.
808  */
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)
812 {
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;
818
819         if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
820                 return (CTF_ERR); /* errno is set for us */
821
822         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
823                 return (CTF_ERR); /* errno is set for us */
824
825         if ((rc = func(name, otype, offset, depth, arg)) != 0)
826                 return (rc);
827
828         kind = LCTF_INFO_KIND(fp, tp->ctt_info);
829
830         if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
831                 return (0);
832
833         (void) ctf_get_ctt_size(fp, tp, &size, &increment);
834
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);
838
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);
844                 }
845
846         } else {
847                 const ctf_lmember_t *lmp = (const ctf_lmember_t *)
848                     ((uintptr_t)tp + increment);
849
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);
856                 }
857         }
858
859         return (0);
860 }
861
862 /*
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.
865  */
866 int
867 ctf_type_visit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg)
868 {
869         return (ctf_type_rvisit(fp, type, func, arg, "", 0, 0));
870 }