]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - cddl/contrib/opensolaris/common/ctf/ctf_types.c
libctf: Handle CTFv3 containers
[FreeBSD/FreeBSD.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 void
31 ctf_get_ctt_index(const ctf_file_t *fp, const void *v, uint_t *indexp,
32     uint_t *typep, int *ischildp)
33 {
34         uint_t index, type;
35         int ischild;
36
37         if (fp->ctf_version == CTF_VERSION_2) {
38                 const struct ctf_type_v2 *ctt = v;
39
40                 type = ctt->ctt_type;
41                 index = CTF_V2_TYPE_TO_INDEX(ctt->ctt_type);
42                 ischild = CTF_V2_TYPE_ISCHILD(ctt->ctt_type);
43         } else {
44                 const struct ctf_type_v3 *ctt = v;
45
46                 type = ctt->ctt_type;
47                 index = CTF_V3_TYPE_TO_INDEX(ctt->ctt_type);
48                 ischild = CTF_V3_TYPE_ISCHILD(ctt->ctt_type);
49         }
50
51         if (indexp != NULL)
52                 *indexp = index;
53         if (typep != NULL)
54                 *typep = type;
55         if (ischildp != NULL)
56                 *ischildp = ischild;
57 }
58
59 void
60 ctf_get_ctt_info(const ctf_file_t *fp, const void *v, uint_t *kindp,
61     uint_t *vlenp, int *isrootp)
62 {
63         uint_t kind, vlen;
64         int isroot;
65
66         if (fp->ctf_version == CTF_VERSION_2) {
67                 const struct ctf_type_v2 *ctt = v;
68
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);
72         } else {
73                 const struct ctf_type_v3 *ctt = v;
74
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);
78         }
79
80         if (kindp != NULL)
81                 *kindp = kind;
82         if (vlenp != NULL)
83                 *vlenp = vlen;
84         if (isrootp != NULL)
85                 *isrootp = isroot;
86 }
87
88 ssize_t
89 ctf_get_ctt_size(const ctf_file_t *fp, const void *v, ssize_t *sizep,
90     ssize_t *incrementp)
91 {
92         ssize_t size, increment;
93
94         if (fp->ctf_version == CTF_VERSION_2) {
95                 const struct ctf_type_v2 *ctt = v;
96
97                 if (ctt->ctt_size == CTF_V2_LSIZE_SENT) {
98                         size = (size_t)CTF_TYPE_LSIZE(ctt);
99                         increment = sizeof (struct ctf_type_v2);
100                 } else {
101                         size = ctt->ctt_size;
102                         increment = sizeof (struct ctf_stype_v2);
103                 }
104         } else {
105                 const struct ctf_type_v3 *ctt = v;
106
107                 if (ctt->ctt_size == CTF_V3_LSIZE_SENT) {
108                         size = (size_t)CTF_TYPE_LSIZE(ctt);
109                         increment = sizeof (struct ctf_type_v3);
110                 } else {
111                         size = ctt->ctt_size;
112                         increment = sizeof (struct ctf_stype_v3);
113                 }
114         }
115
116         if (sizep)
117                 *sizep = size;
118         if (incrementp)
119                 *incrementp = increment;
120
121         return (size);
122 }
123
124 /*
125  * Fetch info for a struct or union member.
126  */
127 void
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)
130 {
131         size_t increment;
132         ulong_t offset;
133         uint_t name, type;
134
135         if (fp->ctf_version == CTF_VERSION_2) {
136                 if (size < CTF_V2_LSTRUCT_THRESH) {
137                         const struct ctf_member_v2 *ctm = v;
138
139                         name = ctm->ctm_name;
140                         type = ctm->ctm_type;
141                         offset = ctm->ctm_offset;
142                         increment = sizeof(*ctm);
143                 } else {
144                         const struct ctf_lmember_v2 *ctlm = v;
145
146                         name = ctlm->ctlm_name;
147                         type = ctlm->ctlm_type;
148                         offset = (ulong_t)CTF_LMEM_OFFSET(ctlm);
149                         increment = sizeof(*ctlm);
150                 }
151         } else {
152                 if (size < CTF_V3_LSTRUCT_THRESH) {
153                         const struct ctf_member_v3 *ctm = v;
154
155                         name = ctm->ctm_name;
156                         type = ctm->ctm_type;
157                         offset = ctm->ctm_offset;
158                         increment = sizeof(*ctm);
159                 } else {
160                         const struct ctf_lmember_v3 *ctlm = v;
161
162                         name = ctlm->ctlm_name;
163                         type = ctlm->ctlm_type;
164                         offset = (ulong_t)CTF_LMEM_OFFSET(ctlm);
165                         increment = sizeof(*ctlm);
166                 }
167         }
168
169         if (incrementp != NULL)
170                 *incrementp = increment;
171         if (typep != NULL)
172                 *typep = type;
173         if (offsetp != NULL)
174                 *offsetp = offset;
175         if (namep != NULL)
176                 *namep = ctf_strraw(fp, name);
177 }
178
179 /*
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.
182  */
183 int
184 ctf_member_iter(ctf_file_t *fp, ctf_id_t type, ctf_member_f *func, void *arg)
185 {
186         ctf_file_t *ofp = fp;
187         const void *tp;
188         ssize_t size, increment;
189         uint_t kind, n, vlen;
190         int rc;
191
192         if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
193                 return (CTF_ERR); /* errno is set for us */
194
195         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
196                 return (CTF_ERR); /* errno is set for us */
197
198         (void) ctf_get_ctt_size(fp, tp, &size, &increment);
199         ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
200
201         if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
202                 return (ctf_set_errno(ofp, ECTF_NOTSOU));
203
204         const char *mp = (const char *)((uintptr_t)tp + increment);
205
206         for (n = vlen; n != 0; n--, mp += increment) {
207                 const char *name;
208                 ulong_t offset;
209                 uint_t type;
210
211                 ctf_get_ctm_info(fp, mp, size, &increment, &type, &offset,
212                     &name);
213                 if ((rc = func(name, type, offset, arg)) != 0)
214                         return (rc);
215         }
216
217         return (0);
218 }
219
220 /*
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.
223  */
224 int
225 ctf_enum_iter(ctf_file_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg)
226 {
227         ctf_file_t *ofp = fp;
228         const void *tp;
229         const ctf_enum_t *ep;
230         ssize_t increment;
231         uint_t kind, n, vlen;
232         int rc;
233
234         if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
235                 return (CTF_ERR); /* errno is set for us */
236
237         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
238                 return (CTF_ERR); /* errno is set for us */
239
240         ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
241         if (kind != CTF_K_ENUM)
242                 return (ctf_set_errno(ofp, ECTF_NOTENUM));
243
244         (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
245
246         ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
247
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)
251                         return (rc);
252         }
253
254         return (0);
255 }
256
257 /*
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.
260  */
261 int
262 ctf_type_iter(ctf_file_t *fp, ctf_type_f *func, void *arg)
263 {
264         ctf_id_t id, max = fp->ctf_typemax;
265         int rc, child = (fp->ctf_flags & LCTF_CHILD);
266         int isroot;
267
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);
271                 if (isroot &&
272                     (rc = func(LCTF_INDEX_TO_TYPE(fp, id, child), arg)) != 0)
273                         return (rc);
274         }
275
276         return (0);
277 }
278
279 /*
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.
285  */
286 ctf_id_t
287 ctf_type_resolve(ctf_file_t *fp, ctf_id_t type)
288 {
289         ctf_id_t prev = type, otype = type;
290         ctf_file_t *ofp = fp;
291         const void *tp;
292         uint_t kind, ctype;
293
294         while ((tp = ctf_lookup_by_id(&fp, type)) != NULL) {
295                 ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
296                 switch (kind) {
297                 case CTF_K_TYPEDEF:
298                 case CTF_K_VOLATILE:
299                 case CTF_K_CONST:
300                 case CTF_K_RESTRICT:
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));
305                         }
306                         prev = type;
307                         type = ctype;
308                         break;
309                 default:
310                         return (type);
311                 }
312         }
313
314         return (CTF_ERR); /* errno is set for us */
315 }
316
317 /*
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.
320  */
321 static ssize_t
322 ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
323     const char *qname)
324 {
325         ctf_decl_t cd;
326         ctf_decl_node_t *cdp;
327         ctf_decl_prec_t prec, lp, rp;
328         int ptr, arr;
329         uint_t k;
330
331         if (fp == NULL && type == CTF_ERR)
332                 return (-1); /* simplify caller code by permitting CTF_ERR */
333
334         ctf_decl_init(&cd, buf, len);
335         ctf_decl_push(&cd, fp, type);
336
337         if (cd.cd_err != 0) {
338                 ctf_decl_fini(&cd);
339                 return (ctf_set_errno(fp, cd.cd_err));
340         }
341
342         /*
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 (*[])().
348          */
349         ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER;
350         arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY;
351
352         rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1;
353         lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1;
354
355         k = CTF_K_POINTER; /* avoid leading whitespace (see below) */
356
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)) {
360
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);
364
365                         if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
366                                 ctf_decl_sprintf(&cd, " ");
367
368                         if (lp == prec) {
369                                 ctf_decl_sprintf(&cd, "(");
370                                 lp = -1;
371                         }
372
373                         switch (cdp->cd_kind) {
374                         case CTF_K_INTEGER:
375                         case CTF_K_FLOAT:
376                         case CTF_K_TYPEDEF:
377                                 if (qname != NULL)
378                                         ctf_decl_sprintf(&cd, "%s`", qname);
379                                 ctf_decl_sprintf(&cd, "%s", name);
380                                 break;
381                         case CTF_K_POINTER:
382                                 ctf_decl_sprintf(&cd, "*");
383                                 break;
384                         case CTF_K_ARRAY:
385                                 ctf_decl_sprintf(&cd, "[%u]", cdp->cd_n);
386                                 break;
387                         case CTF_K_FUNCTION:
388                                 ctf_decl_sprintf(&cd, "()");
389                                 break;
390                         case CTF_K_STRUCT:
391                         case CTF_K_FORWARD:
392                                 ctf_decl_sprintf(&cd, "struct ");
393                                 if (qname != NULL)
394                                         ctf_decl_sprintf(&cd, "%s`", qname);
395                                 ctf_decl_sprintf(&cd, "%s", name);
396                                 break;
397                         case CTF_K_UNION:
398                                 ctf_decl_sprintf(&cd, "union ");
399                                 if (qname != NULL)
400                                         ctf_decl_sprintf(&cd, "%s`", qname);
401                                 ctf_decl_sprintf(&cd, "%s", name);
402                                 break;
403                         case CTF_K_ENUM:
404                                 ctf_decl_sprintf(&cd, "enum ");
405                                 if (qname != NULL)
406                                         ctf_decl_sprintf(&cd, "%s`", qname);
407                                 ctf_decl_sprintf(&cd, "%s", name);
408                                 break;
409                         case CTF_K_VOLATILE:
410                                 ctf_decl_sprintf(&cd, "volatile");
411                                 break;
412                         case CTF_K_CONST:
413                                 ctf_decl_sprintf(&cd, "const");
414                                 break;
415                         case CTF_K_RESTRICT:
416                                 ctf_decl_sprintf(&cd, "restrict");
417                                 break;
418                         }
419
420                         k = cdp->cd_kind;
421                 }
422
423                 if (rp == prec)
424                         ctf_decl_sprintf(&cd, ")");
425         }
426
427         if (cd.cd_len >= len)
428                 (void) ctf_set_errno(fp, ECTF_NAMELEN);
429
430         ctf_decl_fini(&cd);
431         return (cd.cd_len);
432 }
433
434 ssize_t
435 ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
436 {
437         return (ctf_type_qlname(fp, type, buf, len, NULL));
438 }
439
440 /*
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.
443  */
444 char *
445 ctf_type_name(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
446 {
447         ssize_t rv = ctf_type_qlname(fp, type, buf, len, NULL);
448         return (rv >= 0 && rv < len ? buf : NULL);
449 }
450
451 char *
452 ctf_type_qname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
453     const char *qname)
454 {
455         ssize_t rv = ctf_type_qlname(fp, type, buf, len, qname);
456         return (rv >= 0 && rv < len ? buf : NULL);
457 }
458
459 const char *
460 ctf_type_rname(ctf_file_t *fp, const void *v)
461 {
462         uint_t name;
463
464         if (fp->ctf_version == CTF_VERSION_2) {
465                 const struct ctf_type_v2 *ctt = v;
466
467                 name = ctt->ctt_name;
468         } else {
469                 const struct ctf_type_v3 *ctt = v;
470
471                 name = ctt->ctt_name;
472         }
473
474         return (ctf_strptr(fp, name));
475 }
476
477 /*
478  * Resolve the type down to a base type node, and then return the size
479  * of the type storage in bytes.
480  */
481 ssize_t
482 ctf_type_size(ctf_file_t *fp, ctf_id_t type)
483 {
484         const void *tp;
485         ssize_t size;
486         ctf_arinfo_t ar;
487         uint_t kind;
488
489         if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
490                 return (-1); /* errno is set for us */
491
492         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
493                 return (-1); /* errno is set for us */
494
495         ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
496
497         switch (kind) {
498         case CTF_K_POINTER:
499                 return (fp->ctf_dmodel->ctd_pointer);
500
501         case CTF_K_FUNCTION:
502                 return (0); /* function size is only known by symtab */
503
504         case CTF_K_ENUM:
505                 return (fp->ctf_dmodel->ctd_int);
506
507         case CTF_K_ARRAY:
508                 /*
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.
514                  */
515                 if ((size = ctf_get_ctt_size(fp, tp, NULL, NULL)) > 0)
516                         return (size);
517
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 */
521
522                 return (size * ar.ctr_nelems);
523
524         default:
525                 return (ctf_get_ctt_size(fp, tp, NULL, NULL));
526         }
527 }
528
529 /*
530  * Resolve the type down to a base type node, and then return the alignment
531  * needed for the type storage in bytes.
532  */
533 ssize_t
534 ctf_type_align(ctf_file_t *fp, ctf_id_t type)
535 {
536         const void *tp;
537         ctf_arinfo_t r;
538         uint_t kind, vlen;
539
540         if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
541                 return (-1); /* errno is set for us */
542
543         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
544                 return (-1); /* errno is set for us */
545
546         ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
547
548         switch (kind) {
549         case CTF_K_POINTER:
550         case CTF_K_FUNCTION:
551                 return (fp->ctf_dmodel->ctd_pointer);
552
553         case CTF_K_ARRAY:
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));
557
558         case CTF_K_STRUCT:
559         case CTF_K_UNION: {
560                 uint_t n = vlen;
561                 ssize_t size, increment;
562                 size_t align = 0;
563                 const void *vmp;
564
565                 (void) ctf_get_ctt_size(fp, tp, &size, &increment);
566                 vmp = (uchar_t *)tp + increment;
567
568                 if (kind == CTF_K_STRUCT)
569                         n = MIN(n, 1); /* only use first member for structs */
570
571                 for (const char *mp = vmp; n != 0; n--, mp += increment) {
572                         uint_t type;
573
574                         ctf_get_ctm_info(fp, mp, size, &increment, &type,
575                             NULL, NULL);
576                         ssize_t am = ctf_type_align(fp, type);
577                         align = MAX(align, am);
578                 }
579
580                 return (align);
581         }
582
583         case CTF_K_ENUM:
584                 return (fp->ctf_dmodel->ctd_int);
585
586         default:
587                 return (ctf_get_ctt_size(fp, tp, NULL, NULL));
588         }
589 }
590
591 /*
592  * Return the kind (CTF_K_* constant) for the specified type ID.
593  */
594 int
595 ctf_type_kind(ctf_file_t *fp, ctf_id_t type)
596 {
597         const void *tp;
598         uint_t kind;
599
600         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
601                 return (CTF_ERR); /* errno is set for us */
602
603         ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
604
605         return (kind);
606 }
607
608 /*
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.
611  */
612 ctf_id_t
613 ctf_type_reference(ctf_file_t *fp, ctf_id_t type)
614 {
615         ctf_file_t *ofp = fp;
616         const void *tp;
617         uint_t ctype, kind;
618
619         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
620                 return (CTF_ERR); /* errno is set for us */
621
622         ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
623
624         switch (kind) {
625         case CTF_K_POINTER:
626         case CTF_K_TYPEDEF:
627         case CTF_K_VOLATILE:
628         case CTF_K_CONST:
629         case CTF_K_RESTRICT:
630                 ctf_get_ctt_index(fp, tp, NULL, &ctype, NULL);
631                 return (ctype);
632         default:
633                 return (ctf_set_errno(ofp, ECTF_NOTREF));
634         }
635 }
636
637 /*
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.
643  */
644 ctf_id_t
645 ctf_type_pointer(ctf_file_t *fp, ctf_id_t type)
646 {
647         ctf_file_t *ofp = fp;
648         ctf_id_t ntype;
649
650         if (ctf_lookup_by_id(&fp, type) == NULL)
651                 return (CTF_ERR); /* errno is set for us */
652
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)));
655
656         if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
657                 return (ctf_set_errno(ofp, ECTF_NOTYPE));
658
659         if (ctf_lookup_by_id(&fp, type) == NULL)
660                 return (ctf_set_errno(ofp, ECTF_NOTYPE));
661
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)));
664
665         return (ctf_set_errno(ofp, ECTF_NOTYPE));
666 }
667
668 /*
669  * Return the encoding for the specified INTEGER or FLOAT.
670  */
671 int
672 ctf_type_encoding(ctf_file_t *fp, ctf_id_t type, ctf_encoding_t *ep)
673 {
674         ctf_file_t *ofp = fp;
675         const void *tp;
676         ssize_t increment;
677         uint_t data, kind;
678
679         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
680                 return (CTF_ERR); /* errno is set for us */
681
682         (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
683         ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
684
685         switch (kind) {
686         case CTF_K_INTEGER:
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);
691                 break;
692         case CTF_K_FLOAT:
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);
697                 break;
698         default:
699                 return (ctf_set_errno(ofp, ECTF_NOTINTFP));
700         }
701
702         return (0);
703 }
704
705 int
706 ctf_type_cmp(ctf_file_t *lfp, ctf_id_t ltype, ctf_file_t *rfp, ctf_id_t rtype)
707 {
708         int rval;
709
710         if (ltype < rtype)
711                 rval = -1;
712         else if (ltype > rtype)
713                 rval = 1;
714         else
715                 rval = 0;
716
717         if (lfp == rfp)
718                 return (rval);
719
720         if (LCTF_TYPE_ISPARENT(lfp, ltype) && lfp->ctf_parent != NULL)
721                 lfp = lfp->ctf_parent;
722
723         if (LCTF_TYPE_ISPARENT(rfp, rtype) && rfp->ctf_parent != NULL)
724                 rfp = rfp->ctf_parent;
725
726         if (lfp < rfp)
727                 return (-1);
728
729         if (lfp > rfp)
730                 return (1);
731
732         return (rval);
733 }
734
735 /*
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.
740  */
741 int
742 ctf_type_compat(ctf_file_t *lfp, ctf_id_t ltype,
743     ctf_file_t *rfp, ctf_id_t rtype)
744 {
745         const void *ltp, *rtp;
746         ctf_encoding_t le, re;
747         ctf_arinfo_t la, ra;
748         uint_t lkind, rkind;
749
750         if (ctf_type_cmp(lfp, ltype, rfp, rtype) == 0)
751                 return (1);
752
753         ltype = ctf_type_resolve(lfp, ltype);
754         lkind = ctf_type_kind(lfp, ltype);
755
756         rtype = ctf_type_resolve(rfp, rtype);
757         rkind = ctf_type_kind(rfp, rtype);
758
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)
763                 return (0);
764
765         switch (lkind) {
766         case CTF_K_INTEGER:
767         case CTF_K_FLOAT:
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);
771         case CTF_K_POINTER:
772                 return (ctf_type_compat(lfp, ctf_type_reference(lfp, ltype),
773                     rfp, ctf_type_reference(rfp, rtype)));
774         case CTF_K_ARRAY:
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));
780         case CTF_K_STRUCT:
781         case CTF_K_UNION:
782                 return (ctf_type_size(lfp, ltype) == ctf_type_size(rfp, rtype));
783         case CTF_K_ENUM:
784         case CTF_K_FORWARD:
785                 return (1); /* no other checks required for these type kinds */
786         default:
787                 return (0); /* should not get here since we did a resolve */
788         }
789 }
790
791 static int
792 _ctf_member_info(ctf_file_t *fp, ctf_id_t type, const char *name, ulong_t off,
793     ctf_membinfo_t *mip)
794 {
795         ctf_file_t *ofp = fp;
796         const void *tp;
797         ssize_t size, increment;
798         uint_t kind, n, vlen;
799
800         if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
801                 return (CTF_ERR); /* errno is set for us */
802
803         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
804                 return (CTF_ERR); /* errno is set for us */
805
806         (void) ctf_get_ctt_size(fp, tp, &size, &increment);
807         ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
808
809         if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
810                 return (ctf_set_errno(ofp, ECTF_NOTSOU));
811
812         const char *mp = (const char *)((uintptr_t)tp + increment);
813
814         for (n = vlen; n != 0; n--, mp += increment) {
815                 const char *name1;
816                 ulong_t offset;
817                 uint_t type;
818
819                 ctf_get_ctm_info(fp, mp, size, &increment, &type, &offset,
820                     &name1);
821                 if (name1 == NULL &&
822                     _ctf_member_info(fp, type, name1, offset + off, mip) == 0)
823                         return (0);
824                 if (strcmp(name1, name) == 0) {
825                         mip->ctm_type = type;
826                         mip->ctm_offset = offset + off;
827                         return (0);
828                 }
829         }
830
831         return (ctf_set_errno(ofp, ECTF_NOMEMBNAM));
832 }
833
834 /*
835  * Return the type and offset for a given member of a STRUCT or UNION.
836  */
837 int
838 ctf_member_info(ctf_file_t *fp, ctf_id_t type, const char *name,
839     ctf_membinfo_t *mip)
840 {
841
842         return (_ctf_member_info(fp, type, name, 0, mip));
843 }
844
845 /*
846  * Return the array type, index, and size information for the specified ARRAY.
847  */
848 int
849 ctf_array_info(ctf_file_t *fp, ctf_id_t type, ctf_arinfo_t *arp)
850 {
851         ctf_file_t *ofp = fp;
852         const void *ap, *tp;
853         ssize_t increment;
854         uint_t kind;
855
856         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
857                 return (CTF_ERR); /* errno is set for us */
858
859         ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
860
861         if (kind != CTF_K_ARRAY)
862                 return (ctf_set_errno(ofp, ECTF_NOTARRAY));
863
864         (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
865
866         ap = (const void *)((uintptr_t)tp + increment);
867         if (fp->ctf_version == CTF_VERSION_2) {
868                 const struct ctf_array_v2 *ap2 = ap;
869
870                 arp->ctr_contents = ap2->cta_contents;
871                 arp->ctr_index = ap2->cta_index;
872                 arp->ctr_nelems = ap2->cta_nelems;
873         } else {
874                 const struct ctf_array_v3 *ap3 = ap;
875
876                 arp->ctr_contents = ap3->cta_contents;
877                 arp->ctr_index = ap3->cta_index;
878                 arp->ctr_nelems = ap3->cta_nelems;
879         }
880
881         return (0);
882 }
883
884 /*
885  * Convert the specified value to the corresponding enum member name, if a
886  * matching name can be found.  Otherwise NULL is returned.
887  */
888 const char *
889 ctf_enum_name(ctf_file_t *fp, ctf_id_t type, int value)
890 {
891         ctf_file_t *ofp = fp;
892         const void *tp;
893         const ctf_enum_t *ep;
894         ssize_t increment;
895         uint_t kind, n, vlen;
896
897         if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
898                 return (NULL); /* errno is set for us */
899
900         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
901                 return (NULL); /* errno is set for us */
902
903         ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
904
905         if (kind != CTF_K_ENUM) {
906                 (void) ctf_set_errno(ofp, ECTF_NOTENUM);
907                 return (NULL);
908         }
909
910         (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
911
912         ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
913
914         for (n = vlen; n != 0; n--, ep++) {
915                 if (ep->cte_value == value)
916                         return (ctf_strptr(fp, ep->cte_name));
917         }
918
919         (void) ctf_set_errno(ofp, ECTF_NOENUMNAM);
920         return (NULL);
921 }
922
923 /*
924  * Convert the specified enum tag name to the corresponding value, if a
925  * matching name can be found.  Otherwise CTF_ERR is returned.
926  */
927 int
928 ctf_enum_value(ctf_file_t *fp, ctf_id_t type, const char *name, int *valp)
929 {
930         ctf_file_t *ofp = fp;
931         const void *tp;
932         const ctf_enum_t *ep;
933         ssize_t size, increment;
934         uint_t kind, n, vlen;
935
936         if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
937                 return (CTF_ERR); /* errno is set for us */
938
939         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
940                 return (CTF_ERR); /* errno is set for us */
941
942         ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
943
944         if (kind != CTF_K_ENUM) {
945                 (void) ctf_set_errno(ofp, ECTF_NOTENUM);
946                 return (CTF_ERR);
947         }
948
949         (void) ctf_get_ctt_size(fp, tp, &size, &increment);
950
951         ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
952
953         for (n = vlen; n != 0; n--, ep++) {
954                 if (strcmp(ctf_strptr(fp, ep->cte_name), name) == 0) {
955                         if (valp != NULL)
956                                 *valp = ep->cte_value;
957                         return (0);
958                 }
959         }
960
961         (void) ctf_set_errno(ofp, ECTF_NOENUMNAM);
962         return (CTF_ERR);
963 }
964
965 /*
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.
971  */
972 static int
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)
975 {
976         ctf_id_t otype = type;
977         const void *tp;
978         ssize_t size, increment;
979         uint_t kind, n, vlen;
980         int rc;
981
982         if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
983                 return (CTF_ERR); /* errno is set for us */
984
985         if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
986                 return (CTF_ERR); /* errno is set for us */
987
988         if ((rc = func(name, otype, offset, depth, arg)) != 0)
989                 return (rc);
990
991         ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
992
993         if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
994                 return (0);
995
996         (void) ctf_get_ctt_size(fp, tp, &size, &increment);
997
998         const char *mp = (const char *)((uintptr_t)tp + increment);
999         for (n = vlen; n != 0; n--, mp += increment) {
1000                 const char *name;
1001                 ulong_t offset1;
1002                 uint_t type;
1003
1004                 ctf_get_ctm_info(fp, mp, size, &increment, &type, &offset1,
1005                     &name);
1006                 if ((rc = ctf_type_rvisit(fp, type, func, arg, name,
1007                     offset + offset1, depth + 1)) != 0)
1008                         return (rc);
1009         }
1010
1011         return (0);
1012 }
1013
1014 /*
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.
1017  */
1018 int
1019 ctf_type_visit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg)
1020 {
1021         return (ctf_type_rvisit(fp, type, func, arg, "", 0, 0));
1022 }