Revert patch that disables building libctf for non-ELF based targets.
[external/binutils.git] / libctf / ctf-types.c
1 /* Type handling functions.
2    Copyright (C) 2019 Free Software Foundation, Inc.
3
4    This file is part of libctf.
5
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
9    version.
10
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.
15
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/>.  */
19
20 #include <ctf-impl.h>
21 #include <string.h>
22
23 /* Determine whether a type is a parent or a child.  */
24
25 int
26 ctf_type_isparent (ctf_file_t *fp, ctf_id_t id)
27 {
28   return (LCTF_TYPE_ISPARENT (fp, id));
29 }
30
31 int
32 ctf_type_ischild (ctf_file_t * fp, ctf_id_t id)
33 {
34   return (LCTF_TYPE_ISCHILD (fp, id));
35 }
36
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.  */
39
40 int
41 ctf_member_iter (ctf_file_t *fp, ctf_id_t type, ctf_member_f *func, void *arg)
42 {
43   ctf_file_t *ofp = fp;
44   const ctf_type_t *tp;
45   ssize_t size, increment;
46   uint32_t kind, n;
47   int rc;
48
49   if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
50     return -1;                  /* errno is set for us.  */
51
52   if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
53     return -1;                  /* errno is set for us.  */
54
55   (void) ctf_get_ctt_size (fp, tp, &size, &increment);
56   kind = LCTF_INFO_KIND (fp, tp->ctt_info);
57
58   if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
59     return (ctf_set_errno (ofp, ECTF_NOTSOU));
60
61   if (size < CTF_LSTRUCT_THRESH)
62     {
63       const ctf_member_t *mp = (const ctf_member_t *) ((uintptr_t) tp +
64                                                        increment);
65
66       for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, mp++)
67         {
68           const char *name = ctf_strptr (fp, mp->ctm_name);
69           if ((rc = func (name, mp->ctm_type, mp->ctm_offset, arg)) != 0)
70             return rc;
71         }
72
73     }
74   else
75     {
76       const ctf_lmember_t *lmp = (const ctf_lmember_t *) ((uintptr_t) tp +
77                                                           increment);
78
79       for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, lmp++)
80         {
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)
84             return rc;
85         }
86     }
87
88   return 0;
89 }
90
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.  */
93
94 int
95 ctf_enum_iter (ctf_file_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg)
96 {
97   ctf_file_t *ofp = fp;
98   const ctf_type_t *tp;
99   const ctf_enum_t *ep;
100   ssize_t increment;
101   uint32_t n;
102   int rc;
103
104   if ((type = ctf_type_resolve_unsliced (fp, type)) == CTF_ERR)
105     return -1;                  /* errno is set for us.  */
106
107   if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
108     return -1;                  /* errno is set for us.  */
109
110   if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ENUM)
111     return (ctf_set_errno (ofp, ECTF_NOTENUM));
112
113   (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
114
115   ep = (const ctf_enum_t *) ((uintptr_t) tp + increment);
116
117   for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++)
118     {
119       const char *name = ctf_strptr (fp, ep->cte_name);
120       if ((rc = func (name, ep->cte_value, arg)) != 0)
121         return rc;
122     }
123
124   return 0;
125 }
126
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.  */
129
130 int
131 ctf_type_iter (ctf_file_t *fp, ctf_type_f *func, void *arg)
132 {
133   ctf_id_t id, max = fp->ctf_typemax;
134   int rc, child = (fp->ctf_flags & LCTF_CHILD);
135
136   for (id = 1; id <= max; id++)
137     {
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)
141         return rc;
142     }
143
144   return 0;
145 }
146
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.  */
149
150 int
151 ctf_variable_iter (ctf_file_t *fp, ctf_variable_f *func, void *arg)
152 {
153   unsigned long i;
154   int rc;
155
156   if ((fp->ctf_flags & LCTF_CHILD) && (fp->ctf_parent == NULL))
157     return ECTF_NOPARENT;
158
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)
162       return rc;
163
164   return 0;
165 }
166
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.
172
173    Does not drill down through slices to their contained type.  */
174
175 ctf_id_t
176 ctf_type_resolve (ctf_file_t *fp, ctf_id_t type)
177 {
178   ctf_id_t prev = type, otype = type;
179   ctf_file_t *ofp = fp;
180   const ctf_type_t *tp;
181
182   while ((tp = ctf_lookup_by_id (&fp, type)) != NULL)
183     {
184       switch (LCTF_INFO_KIND (fp, tp->ctt_info))
185         {
186         case CTF_K_TYPEDEF:
187         case CTF_K_VOLATILE:
188         case CTF_K_CONST:
189         case CTF_K_RESTRICT:
190           if (tp->ctt_type == type || tp->ctt_type == otype
191               || tp->ctt_type == prev)
192             {
193               ctf_dprintf ("type %ld cycle detected\n", otype);
194               return (ctf_set_errno (ofp, ECTF_CORRUPT));
195             }
196           prev = type;
197           type = tp->ctt_type;
198           break;
199         default:
200           return type;
201         }
202     }
203
204   return CTF_ERR;               /* errno is set for us.  */
205 }
206
207 /* Like ctf_type_resolve(), but traverse down through slices to their contained
208    type.  */
209
210 ctf_id_t
211 ctf_type_resolve_unsliced (ctf_file_t *fp, ctf_id_t type)
212 {
213   const ctf_type_t *tp;
214
215   if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
216     return -1;
217
218   if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
219     return CTF_ERR;             /* errno is set for us.  */
220
221   if ((LCTF_INFO_KIND (fp, tp->ctt_info)) == CTF_K_SLICE)
222     return ctf_type_reference (fp, type);
223   return type;
224 }
225
226 /* Lookup the given type ID and return its name as a new dynamcally-allocated
227    string.  */
228
229 char *
230 ctf_type_aname (ctf_file_t *fp, ctf_id_t type)
231 {
232   ctf_decl_t cd;
233   ctf_decl_node_t *cdp;
234   ctf_decl_prec_t prec, lp, rp;
235   int ptr, arr;
236   uint32_t k;
237   char *buf;
238
239   if (fp == NULL && type == CTF_ERR)
240     return NULL;        /* Simplify caller code by permitting CTF_ERR.  */
241
242   ctf_decl_init (&cd);
243   ctf_decl_push (&cd, fp, type);
244
245   if (cd.cd_err != 0)
246     {
247       ctf_decl_fini (&cd);
248       ctf_set_errno (fp, cd.cd_err);
249       return NULL;
250     }
251
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 (*[])().  */
257
258   ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER;
259   arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY;
260
261   rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1;
262   lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1;
263
264   k = CTF_K_POINTER;            /* Avoid leading whitespace (see below).  */
265
266   for (prec = CTF_PREC_BASE; prec < CTF_PREC_MAX; prec++)
267     {
268       for (cdp = ctf_list_next (&cd.cd_nodes[prec]);
269            cdp != NULL; cdp = ctf_list_next (cdp))
270         {
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);
274
275           if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
276             ctf_decl_sprintf (&cd, " ");
277
278           if (lp == prec)
279             {
280               ctf_decl_sprintf (&cd, "(");
281               lp = -1;
282             }
283
284           switch (cdp->cd_kind)
285             {
286             case CTF_K_INTEGER:
287             case CTF_K_FLOAT:
288             case CTF_K_TYPEDEF:
289               ctf_decl_sprintf (&cd, "%s", name);
290               break;
291             case CTF_K_POINTER:
292               ctf_decl_sprintf (&cd, "*");
293               break;
294             case CTF_K_ARRAY:
295               ctf_decl_sprintf (&cd, "[%u]", cdp->cd_n);
296               break;
297             case CTF_K_FUNCTION:
298               ctf_decl_sprintf (&cd, "()");
299               break;
300             case CTF_K_STRUCT:
301             case CTF_K_FORWARD:
302               ctf_decl_sprintf (&cd, "struct %s", name);
303               break;
304             case CTF_K_UNION:
305               ctf_decl_sprintf (&cd, "union %s", name);
306               break;
307             case CTF_K_ENUM:
308               ctf_decl_sprintf (&cd, "enum %s", name);
309               break;
310             case CTF_K_VOLATILE:
311               ctf_decl_sprintf (&cd, "volatile");
312               break;
313             case CTF_K_CONST:
314               ctf_decl_sprintf (&cd, "const");
315               break;
316             case CTF_K_RESTRICT:
317               ctf_decl_sprintf (&cd, "restrict");
318               break;
319             case CTF_K_SLICE:
320               /* No representation: just changes encoding of contained type,
321                  which is not in any case printed.  Skip it.  */
322               break;
323             }
324
325           k = cdp->cd_kind;
326         }
327
328       if (rp == prec)
329         ctf_decl_sprintf (&cd, ")");
330     }
331
332   if (cd.cd_enomem)
333     (void) ctf_set_errno (fp, ENOMEM);
334
335   buf = ctf_decl_buf (&cd);
336
337   ctf_decl_fini (&cd);
338   return buf;
339 }
340
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.  */
343
344 ssize_t
345 ctf_type_lname (ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
346 {
347   char *str = ctf_type_aname (fp, type);
348   size_t slen = strlen (str);
349
350   if (str == NULL)
351     return CTF_ERR;             /* errno is set for us */
352
353   snprintf (buf, len, "%s", str);
354   free (str);
355
356   if (slen >= len)
357     (void) ctf_set_errno (fp, ECTF_NAMELEN);
358
359   return slen;
360 }
361
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.  */
364
365 char *
366 ctf_type_name (ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
367 {
368   ssize_t rv = ctf_type_lname (fp, type, buf, len);
369   return (rv >= 0 && (size_t) rv < len ? buf : NULL);
370 }
371
372 /* Resolve the type down to a base type node, and then return the size
373    of the type storage in bytes.  */
374
375 ssize_t
376 ctf_type_size (ctf_file_t *fp, ctf_id_t type)
377 {
378   const ctf_type_t *tp;
379   ssize_t size;
380   ctf_arinfo_t ar;
381
382   if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
383     return -1;                  /* errno is set for us.  */
384
385   if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
386     return -1;                  /* errno is set for us.  */
387
388   switch (LCTF_INFO_KIND (fp, tp->ctt_info))
389     {
390     case CTF_K_POINTER:
391       return fp->ctf_dmodel->ctd_pointer;
392
393     case CTF_K_FUNCTION:
394       return 0;         /* Function size is only known by symtab.  */
395
396     case CTF_K_ENUM:
397       return fp->ctf_dmodel->ctd_int;
398
399     case CTF_K_ARRAY:
400       /* ctf_add_array() does not directly encode the element size, but
401          requires the user to multiply to determine the element size.
402
403          If ctf_get_ctt_size() returns nonzero, then use the recorded
404          size instead.  */
405
406       if ((size = ctf_get_ctt_size (fp, tp, NULL, NULL)) > 0)
407         return size;
408
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.  */
412
413       return size * ar.ctr_nelems;
414
415     default: /* including slices of enums, etc */
416       return (ctf_get_ctt_size (fp, tp, NULL, NULL));
417     }
418 }
419
420 /* Resolve the type down to a base type node, and then return the alignment
421    needed for the type storage in bytes.
422
423    XXX may need arch-dependent attention.  */
424
425 ssize_t
426 ctf_type_align (ctf_file_t *fp, ctf_id_t type)
427 {
428   const ctf_type_t *tp;
429   ctf_file_t *ofp = fp;
430   int kind;
431
432   if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
433     return -1;                  /* errno is set for us.  */
434
435   if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
436     return -1;                  /* errno is set for us.  */
437
438   kind = LCTF_INFO_KIND (fp, tp->ctt_info);
439   switch (kind)
440     {
441     case CTF_K_POINTER:
442     case CTF_K_FUNCTION:
443       return fp->ctf_dmodel->ctd_pointer;
444
445     case CTF_K_ARRAY:
446       {
447         ctf_arinfo_t r;
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));
451       }
452
453     case CTF_K_STRUCT:
454     case CTF_K_UNION:
455       {
456         size_t align = 0;
457         ctf_dtdef_t *dtd;
458
459         if ((dtd = ctf_dynamic_type (ofp, type)) == NULL)
460           {
461             uint32_t n = LCTF_INFO_VLEN (fp, tp->ctt_info);
462             ssize_t size, increment;
463             const void *vmp;
464
465             (void) ctf_get_ctt_size (fp, tp, &size, &increment);
466             vmp = (unsigned char *) tp + increment;
467
468             if (kind == CTF_K_STRUCT)
469               n = MIN (n, 1);   /* Only use first member for structs.  */
470
471             if (size < CTF_LSTRUCT_THRESH)
472               {
473                 const ctf_member_t *mp = vmp;
474                 for (; n != 0; n--, mp++)
475                   {
476                     ssize_t am = ctf_type_align (fp, mp->ctm_type);
477                     align = MAX (align, (size_t) am);
478                   }
479               }
480             else
481               {
482                 const ctf_lmember_t *lmp = vmp;
483                 for (; n != 0; n--, lmp++)
484                   {
485                     ssize_t am = ctf_type_align (fp, lmp->ctlm_type);
486                     align = MAX (align, (size_t) am);
487                   }
488               }
489           }
490         else
491           {
492               ctf_dmdef_t *dmd;
493
494               for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
495                    dmd != NULL; dmd = ctf_list_next (dmd))
496                 {
497                   ssize_t am = ctf_type_align (fp, dmd->dmd_type);
498                   align = MAX (align, (size_t) am);
499                   if (kind == CTF_K_STRUCT)
500                     break;
501                 }
502           }
503
504         return align;
505       }
506
507     case CTF_K_ENUM:
508       return fp->ctf_dmodel->ctd_int;
509
510     default:  /* including slices of enums, etc */
511       return (ctf_get_ctt_size (fp, tp, NULL, NULL));
512     }
513 }
514
515 /* Return the kind (CTF_K_* constant) for the specified type ID.  */
516
517 int
518 ctf_type_kind_unsliced (ctf_file_t *fp, ctf_id_t type)
519 {
520   const ctf_type_t *tp;
521
522   if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
523     return -1;                  /* errno is set for us.  */
524
525   return (LCTF_INFO_KIND (fp, tp->ctt_info));
526 }
527
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.  */
530
531 int
532 ctf_type_kind (ctf_file_t *fp, ctf_id_t type)
533 {
534   int kind;
535
536   if ((kind = ctf_type_kind_unsliced (fp, type)) < 0)
537     return -1;
538
539   if (kind == CTF_K_SLICE)
540     {
541       if ((type = ctf_type_reference (fp, type)) == CTF_ERR)
542         return -1;
543       kind = ctf_type_kind_unsliced (fp, type);
544     }
545
546   return kind;
547 }
548
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.  */
551
552 ctf_id_t
553 ctf_type_reference (ctf_file_t *fp, ctf_id_t type)
554 {
555   ctf_file_t *ofp = fp;
556   const ctf_type_t *tp;
557
558   if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
559     return CTF_ERR;             /* errno is set for us.  */
560
561   switch (LCTF_INFO_KIND (fp, tp->ctt_info))
562     {
563     case CTF_K_POINTER:
564     case CTF_K_TYPEDEF:
565     case CTF_K_VOLATILE:
566     case CTF_K_CONST:
567     case CTF_K_RESTRICT:
568       return tp->ctt_type;
569       /* Slices store their type in an unusual place.  */
570     case CTF_K_SLICE:
571       {
572         const ctf_slice_t *sp;
573         ssize_t increment;
574         (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
575         sp = (const ctf_slice_t *) ((uintptr_t) tp + increment);
576         return sp->cts_type;
577       }
578     default:
579       return (ctf_set_errno (ofp, ECTF_NOTREF));
580     }
581 }
582
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.
588
589    XXX what about parent containers?  */
590
591 ctf_id_t
592 ctf_type_pointer (ctf_file_t *fp, ctf_id_t type)
593 {
594   ctf_file_t *ofp = fp;
595   ctf_id_t ntype;
596
597   if (ctf_lookup_by_id (&fp, type) == NULL)
598     return CTF_ERR;             /* errno is set for us.  */
599
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)));
602
603   if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
604     return (ctf_set_errno (ofp, ECTF_NOTYPE));
605
606   if (ctf_lookup_by_id (&fp, type) == NULL)
607     return (ctf_set_errno (ofp, ECTF_NOTYPE));
608
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)));
611
612   return (ctf_set_errno (ofp, ECTF_NOTYPE));
613 }
614
615 /* Return the encoding for the specified INTEGER or FLOAT.  */
616
617 int
618 ctf_type_encoding (ctf_file_t *fp, ctf_id_t type, ctf_encoding_t *ep)
619 {
620   ctf_file_t *ofp = fp;
621   ctf_dtdef_t *dtd;
622   const ctf_type_t *tp;
623   ssize_t increment;
624   uint32_t data;
625
626   if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
627     return -1;                  /* errno is set for us.  */
628
629   if ((dtd = ctf_dynamic_type (ofp, type)) != NULL)
630     {
631       *ep = dtd->dtd_u.dtu_enc;
632       return 0;
633     }
634
635   (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
636
637   switch (LCTF_INFO_KIND (fp, tp->ctt_info))
638     {
639     case CTF_K_INTEGER:
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);
644       break;
645     case CTF_K_FLOAT:
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);
650       break;
651     case CTF_K_SLICE:
652       {
653         const ctf_slice_t *slice;
654         ctf_encoding_t underlying_en;
655
656         slice = (ctf_slice_t *) ((uintptr_t) tp + increment);
657         data = ctf_type_encoding (fp, slice->cts_type, &underlying_en);
658
659         ep->cte_format = underlying_en.cte_format;
660         ep->cte_offset = slice->cts_offset;
661         ep->cte_bits = slice->cts_bits;
662         break;
663       }
664     default:
665       return (ctf_set_errno (ofp, ECTF_NOTINTFP));
666     }
667
668   return 0;
669 }
670
671 int
672 ctf_type_cmp (ctf_file_t *lfp, ctf_id_t ltype, ctf_file_t *rfp,
673               ctf_id_t rtype)
674 {
675   int rval;
676
677   if (ltype < rtype)
678     rval = -1;
679   else if (ltype > rtype)
680     rval = 1;
681   else
682     rval = 0;
683
684   if (lfp == rfp)
685     return rval;
686
687   if (LCTF_TYPE_ISPARENT (lfp, ltype) && lfp->ctf_parent != NULL)
688     lfp = lfp->ctf_parent;
689
690   if (LCTF_TYPE_ISPARENT (rfp, rtype) && rfp->ctf_parent != NULL)
691     rfp = rfp->ctf_parent;
692
693   if (lfp < rfp)
694     return -1;
695
696   if (lfp > rfp)
697     return 1;
698
699   return rval;
700 }
701
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.  */
707
708 int
709 ctf_type_compat (ctf_file_t *lfp, ctf_id_t ltype,
710                  ctf_file_t *rfp, ctf_id_t rtype)
711 {
712   const ctf_type_t *ltp, *rtp;
713   ctf_encoding_t le, re;
714   ctf_arinfo_t la, ra;
715   uint32_t lkind, rkind;
716   int same_names = 0;
717
718   if (ctf_type_cmp (lfp, ltype, rfp, rtype) == 0)
719     return 1;
720
721   ltype = ctf_type_resolve (lfp, ltype);
722   lkind = ctf_type_kind (lfp, ltype);
723
724   rtype = ctf_type_resolve (rfp, rtype);
725   rkind = ctf_type_kind (rfp, rtype);
726
727   ltp = ctf_lookup_by_id (&lfp, ltype);
728   rtp = ctf_lookup_by_id (&rfp, rtype);
729
730   if (ltp != NULL && rtp != NULL)
731     same_names = (strcmp (ctf_strptr (lfp, ltp->ctt_name),
732                           ctf_strptr (rfp, rtp->ctt_name)) == 0);
733
734   if (((lkind == CTF_K_ENUM) && (rkind == CTF_K_INTEGER)) ||
735       ((rkind == CTF_K_ENUM) && (lkind == CTF_K_INTEGER)))
736     return 1;
737
738   if (lkind != rkind)
739     return 0;
740
741   switch (lkind)
742     {
743     case CTF_K_INTEGER:
744     case CTF_K_FLOAT:
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);
750     case CTF_K_POINTER:
751       return (ctf_type_compat (lfp, ctf_type_reference (lfp, ltype),
752                                rfp, ctf_type_reference (rfp, rtype)));
753     case CTF_K_ARRAY:
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));
759     case CTF_K_STRUCT:
760     case CTF_K_UNION:
761       return (same_names && (ctf_type_size (lfp, ltype)
762                              == ctf_type_size (rfp, rtype)));
763     case CTF_K_ENUM:
764       {
765         int lencoded, rencoded;
766         lencoded = ctf_type_encoding (lfp, ltype, &le);
767         rencoded = ctf_type_encoding (rfp, rtype, &re);
768
769         if ((lencoded != rencoded) ||
770             ((lencoded == 0) && memcmp (&le, &re, sizeof (ctf_encoding_t)) != 0))
771           return 0;
772       }
773       /* FALLTHRU */
774     case CTF_K_FORWARD:
775       return same_names;   /* No other checks required for these type kinds.  */
776     default:
777       return 0;               /* Should not get here since we did a resolve.  */
778     }
779 }
780
781 /* Return the type and offset for a given member of a STRUCT or UNION.  */
782
783 int
784 ctf_member_info (ctf_file_t *fp, ctf_id_t type, const char *name,
785                  ctf_membinfo_t *mip)
786 {
787   ctf_file_t *ofp = fp;
788   const ctf_type_t *tp;
789   ssize_t size, increment;
790   uint32_t kind, n;
791
792   if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
793     return -1;                  /* errno is set for us.  */
794
795   if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
796     return -1;                  /* errno is set for us.  */
797
798   (void) ctf_get_ctt_size (fp, tp, &size, &increment);
799   kind = LCTF_INFO_KIND (fp, tp->ctt_info);
800
801   if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
802     return (ctf_set_errno (ofp, ECTF_NOTSOU));
803
804   if (size < CTF_LSTRUCT_THRESH)
805     {
806       const ctf_member_t *mp = (const ctf_member_t *) ((uintptr_t) tp +
807                                                        increment);
808
809       for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, mp++)
810         {
811           if (strcmp (ctf_strptr (fp, mp->ctm_name), name) == 0)
812             {
813               mip->ctm_type = mp->ctm_type;
814               mip->ctm_offset = mp->ctm_offset;
815               return 0;
816             }
817         }
818     }
819   else
820     {
821       const ctf_lmember_t *lmp = (const ctf_lmember_t *) ((uintptr_t) tp +
822                                                           increment);
823
824       for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, lmp++)
825         {
826           if (strcmp (ctf_strptr (fp, lmp->ctlm_name), name) == 0)
827             {
828               mip->ctm_type = lmp->ctlm_type;
829               mip->ctm_offset = (unsigned long) CTF_LMEM_OFFSET (lmp);
830               return 0;
831             }
832         }
833     }
834
835   return (ctf_set_errno (ofp, ECTF_NOMEMBNAM));
836 }
837
838 /* Return the array type, index, and size information for the specified ARRAY.  */
839
840 int
841 ctf_array_info (ctf_file_t *fp, ctf_id_t type, ctf_arinfo_t *arp)
842 {
843   ctf_file_t *ofp = fp;
844   const ctf_type_t *tp;
845   const ctf_array_t *ap;
846   const ctf_dtdef_t *dtd;
847   ssize_t increment;
848
849   if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
850     return -1;                  /* errno is set for us.  */
851
852   if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ARRAY)
853     return (ctf_set_errno (ofp, ECTF_NOTARRAY));
854
855   if ((dtd = ctf_dynamic_type (ofp, type)) != NULL)
856     {
857       *arp = dtd->dtd_u.dtu_arr;
858       return 0;
859     }
860
861   (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
862
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;
867
868   return 0;
869 }
870
871 /* Convert the specified value to the corresponding enum tag name, if a
872    matching name can be found.  Otherwise NULL is returned.  */
873
874 const char *
875 ctf_enum_name (ctf_file_t *fp, ctf_id_t type, int value)
876 {
877   ctf_file_t *ofp = fp;
878   const ctf_type_t *tp;
879   const ctf_enum_t *ep;
880   ssize_t increment;
881   uint32_t n;
882
883   if ((type = ctf_type_resolve_unsliced (fp, type)) == CTF_ERR)
884     return NULL;                /* errno is set for us.  */
885
886   if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
887     return NULL;                /* errno is set for us.  */
888
889   if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ENUM)
890     {
891       (void) ctf_set_errno (ofp, ECTF_NOTENUM);
892       return NULL;
893     }
894
895   (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
896
897   ep = (const ctf_enum_t *) ((uintptr_t) tp + increment);
898
899   for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++)
900     {
901       if (ep->cte_value == value)
902         return (ctf_strptr (fp, ep->cte_name));
903     }
904
905   (void) ctf_set_errno (ofp, ECTF_NOENUMNAM);
906   return NULL;
907 }
908
909 /* Convert the specified enum tag name to the corresponding value, if a
910    matching name can be found.  Otherwise CTF_ERR is returned.  */
911
912 int
913 ctf_enum_value (ctf_file_t * fp, ctf_id_t type, const char *name, int *valp)
914 {
915   ctf_file_t *ofp = fp;
916   const ctf_type_t *tp;
917   const ctf_enum_t *ep;
918   ssize_t increment;
919   uint32_t n;
920
921   if ((type = ctf_type_resolve_unsliced (fp, type)) == CTF_ERR)
922     return -1;                  /* errno is set for us.  */
923
924   if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
925     return -1;                  /* errno is set for us.  */
926
927   if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ENUM)
928     {
929       (void) ctf_set_errno (ofp, ECTF_NOTENUM);
930       return -1;
931     }
932
933   (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
934
935   ep = (const ctf_enum_t *) ((uintptr_t) tp + increment);
936
937   for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++)
938     {
939       if (strcmp (ctf_strptr (fp, ep->cte_name), name) == 0)
940         {
941           if (valp != NULL)
942             *valp = ep->cte_value;
943           return 0;
944         }
945     }
946
947   (void) ctf_set_errno (ofp, ECTF_NOENUMNAM);
948   return -1;
949 }
950
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.  */
956
957 static int
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)
960 {
961   ctf_id_t otype = type;
962   const ctf_type_t *tp;
963   ssize_t size, increment;
964   uint32_t kind, n;
965   int rc;
966
967   if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
968     return -1;                  /* errno is set for us.  */
969
970   if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
971     return -1;                  /* errno is set for us.  */
972
973   if ((rc = func (name, otype, offset, depth, arg)) != 0)
974     return rc;
975
976   kind = LCTF_INFO_KIND (fp, tp->ctt_info);
977
978   if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
979     return 0;
980
981   (void) ctf_get_ctt_size (fp, tp, &size, &increment);
982
983   if (size < CTF_LSTRUCT_THRESH)
984     {
985       const ctf_member_t *mp = (const ctf_member_t *) ((uintptr_t) tp +
986                                                        increment);
987
988       for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, mp++)
989         {
990           if ((rc = ctf_type_rvisit (fp, mp->ctm_type,
991                                      func, arg, ctf_strptr (fp, mp->ctm_name),
992                                      offset + mp->ctm_offset,
993                                      depth + 1)) != 0)
994             return rc;
995         }
996
997     }
998   else
999     {
1000       const ctf_lmember_t *lmp = (const ctf_lmember_t *) ((uintptr_t) tp +
1001                                                           increment);
1002
1003       for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, lmp++)
1004         {
1005           if ((rc = ctf_type_rvisit (fp, lmp->ctlm_type,
1006                                      func, arg, ctf_strptr (fp,
1007                                                             lmp->ctlm_name),
1008                                      offset + (unsigned long) CTF_LMEM_OFFSET (lmp),
1009                                      depth + 1)) != 0)
1010             return rc;
1011         }
1012     }
1013
1014   return 0;
1015 }
1016
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.  */
1019 int
1020 ctf_type_visit (ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg)
1021 {
1022   return (ctf_type_rvisit (fp, type, func, arg, "", 0, 0));
1023 }