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 #ifdef HAVE_NBTOOL_CONFIG_H
23 #include "nbtool_config.h"
24 #endif
25 
26 /*
27  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
28  * Use is subject to license terms.
29  */
30 
31 #include <ctf_impl.h>
32 
33 void
ctf_get_ctt_index(const ctf_file_t * fp,const void * v,uint_t * indexp,uint_t * typep,int * ischildp)34 ctf_get_ctt_index(const ctf_file_t *fp, const void *v, uint_t *indexp,
35     uint_t *typep, int *ischildp)
36 {
37           uint_t index, type;
38           int ischild;
39 
40           if (fp->ctf_version == CTF_VERSION_2) {
41                     const struct ctf_type_v2 *ctt = v;
42 
43                     type = ctt->ctt_type;
44                     index = CTF_V2_TYPE_TO_INDEX(ctt->ctt_type);
45                     ischild = CTF_V2_TYPE_ISCHILD(ctt->ctt_type);
46           } else {
47                     const struct ctf_type_v3 *ctt = v;
48 
49                     type = ctt->ctt_type;
50                     index = CTF_V3_TYPE_TO_INDEX(ctt->ctt_type);
51                     ischild = CTF_V3_TYPE_ISCHILD(ctt->ctt_type);
52           }
53 
54           if (indexp != NULL)
55                     *indexp = index;
56           if (typep != NULL)
57                     *typep = type;
58           if (ischildp != NULL)
59                     *ischildp = ischild;
60 }
61 
62 void
ctf_get_ctt_info(const ctf_file_t * fp,const void * v,uint_t * kindp,uint_t * vlenp,uint_t * isrootp)63 ctf_get_ctt_info(const ctf_file_t *fp, const void *v, uint_t *kindp,
64     uint_t *vlenp, uint_t *isrootp)
65 {
66           uint_t kind, vlen;
67           int isroot;
68 
69           if (fp->ctf_version == CTF_VERSION_2) {
70                     const struct ctf_type_v2 *ctt = v;
71 
72                     kind = CTF_V2_INFO_KIND(ctt->ctt_info);
73                     vlen = CTF_V2_INFO_VLEN(ctt->ctt_info);
74                     isroot = CTF_V2_INFO_ISROOT(ctt->ctt_info);
75           } else {
76                     const struct ctf_type_v3 *ctt = v;
77 
78                     kind = CTF_V3_INFO_KIND(ctt->ctt_info);
79                     vlen = CTF_V3_INFO_VLEN(ctt->ctt_info);
80                     isroot = CTF_V3_INFO_ISROOT(ctt->ctt_info);
81           }
82 
83           if (kindp != NULL)
84                     *kindp = kind;
85           if (vlenp != NULL)
86                     *vlenp = vlen;
87           if (isrootp != NULL)
88                     *isrootp = isroot;
89 }
90 
91 ssize_t
ctf_get_ctt_size(const ctf_file_t * fp,const void * v,ssize_t * sizep,ssize_t * incrementp)92 ctf_get_ctt_size(const ctf_file_t *fp, const void *v, ssize_t *sizep,
93     ssize_t *incrementp)
94 {
95           ssize_t size, increment;
96 
97           if (fp->ctf_version == CTF_VERSION_2) {
98                     const struct ctf_type_v2 *ctt = v;
99 
100                     if (ctt->ctt_size == CTF_V2_LSIZE_SENT) {
101                               size = (size_t)CTF_TYPE_LSIZE(ctt);
102                               increment = sizeof (struct ctf_type_v2);
103                     } else {
104                               size = ctt->ctt_size;
105                               increment = sizeof (struct ctf_stype_v2);
106                     }
107           } else {
108                     const struct ctf_type_v3 *ctt = v;
109 
110                     if (ctt->ctt_size == CTF_V3_LSIZE_SENT) {
111                               size = (size_t)CTF_TYPE_LSIZE(ctt);
112                               increment = sizeof (struct ctf_type_v3);
113                     } else {
114                               size = ctt->ctt_size;
115                               increment = sizeof (struct ctf_stype_v3);
116                     }
117           }
118 
119           if (sizep)
120                     *sizep = size;
121           if (incrementp)
122                     *incrementp = increment;
123 
124           return (size);
125 }
126 
127 /*
128  * Fetch info for a struct or union member.
129  */
130 void
ctf_get_ctm_info(const ctf_file_t * fp,const void * v,ssize_t size,ssize_t * incrementp,uint_t * typep,ulong_t * offsetp,const char ** namep)131 ctf_get_ctm_info(const ctf_file_t *fp, const void *v, ssize_t size,
132     ssize_t *incrementp, uint_t *typep, ulong_t *offsetp, const char **namep)
133 {
134           size_t increment;
135           ulong_t offset;
136           uint_t name, type;
137 
138           if (fp->ctf_version == CTF_VERSION_2) {
139                     if (size < CTF_V2_LSTRUCT_THRESH) {
140                               const struct ctf_member_v2 *ctm = v;
141 
142                               name = ctm->ctm_name;
143                               type = ctm->ctm_type;
144                               offset = ctm->ctm_offset;
145                               increment = sizeof(*ctm);
146                     } else {
147                               const struct ctf_lmember_v2 *ctlm = v;
148 
149                               name = ctlm->ctlm_name;
150                               type = ctlm->ctlm_type;
151                               offset = (ulong_t)CTF_LMEM_OFFSET(ctlm);
152                               increment = sizeof(*ctlm);
153                     }
154           } else {
155                     if (size < CTF_V3_LSTRUCT_THRESH) {
156                               const struct ctf_member_v3 *ctm = v;
157 
158                               name = ctm->ctm_name;
159                               type = ctm->ctm_type;
160                               offset = ctm->ctm_offset;
161                               increment = sizeof(*ctm);
162                     } else {
163                               const struct ctf_lmember_v3 *ctlm = v;
164 
165                               name = ctlm->ctlm_name;
166                               type = ctlm->ctlm_type;
167                               offset = (ulong_t)CTF_LMEM_OFFSET(ctlm);
168                               increment = sizeof(*ctlm);
169                     }
170           }
171 
172           if (incrementp != NULL)
173                     *incrementp = increment;
174           if (typep != NULL)
175                     *typep = type;
176           if (offsetp != NULL)
177                     *offsetp = offset;
178           if (namep != NULL)
179                     *namep = ctf_strraw(fp, name);
180 }
181 
182 /*
183  * Iterate over the members of a STRUCT or UNION.  We pass the name, member
184  * type, and offset of each member to the specified callback function.
185  */
186 int
ctf_member_iter(ctf_file_t * fp,ctf_id_t type,ctf_member_f * func,void * arg)187 ctf_member_iter(ctf_file_t *fp, ctf_id_t type, ctf_member_f *func, void *arg)
188 {
189           ctf_file_t *ofp = fp;
190           const void *tp;
191           ssize_t size, increment;
192           uint_t kind, n, vlen;
193           int rc;
194 
195           if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
196                     return (CTF_ERR); /* errno is set for us */
197 
198           if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
199                     return (CTF_ERR); /* errno is set for us */
200 
201           (void) ctf_get_ctt_size(fp, tp, &size, &increment);
202           ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
203 
204           if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
205                     return (ctf_set_errno(ofp, ECTF_NOTSOU));
206 
207           const char *mp = (const char *)((uintptr_t)tp + increment);
208 
209           for (n = vlen; n != 0; n--, mp += increment) {
210                     const char *name;
211                     ulong_t offset;
212                     uint_t xtype;
213 
214                     ctf_get_ctm_info(fp, mp, size, &increment, &xtype, &offset,
215                         &name);
216                     if ((rc = func(name, xtype, offset, arg)) != 0)
217                               return (rc);
218           }
219 
220           return (0);
221 }
222 
223 /*
224  * Iterate over the members of an ENUM.  We pass the string name and associated
225  * integer value of each enum element to the specified callback function.
226  */
227 int
ctf_enum_iter(ctf_file_t * fp,ctf_id_t type,ctf_enum_f * func,void * arg)228 ctf_enum_iter(ctf_file_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg)
229 {
230           ctf_file_t *ofp = fp;
231           const void *tp;
232           const ctf_enum_t *ep;
233           ssize_t increment;
234           uint_t kind, n, vlen;
235           int rc;
236 
237           if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
238                     return (CTF_ERR); /* errno is set for us */
239 
240           if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
241                     return (CTF_ERR); /* errno is set for us */
242 
243           ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
244           if (kind != CTF_K_ENUM)
245                     return (ctf_set_errno(ofp, ECTF_NOTENUM));
246 
247           (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
248 
249           ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
250 
251           for (n = vlen; n != 0; n--, ep++) {
252                     const char *name = ctf_strptr(fp, ep->cte_name);
253                     if ((rc = func(name, ep->cte_value, arg)) != 0)
254                               return (rc);
255           }
256 
257           return (0);
258 }
259 
260 /*
261  * Iterate over every root (user-visible) type in the given CTF container.
262  * We pass the type ID of each type to the specified callback function.
263  */
264 int
ctf_type_iter(ctf_file_t * fp,ctf_type_f * func,void * arg)265 ctf_type_iter(ctf_file_t *fp, ctf_type_f *func, void *arg)
266 {
267           ctf_id_t id, max = fp->ctf_typemax;
268           int rc, child = (fp->ctf_flags & LCTF_CHILD);
269           uint_t isroot;
270 
271           for (id = 1; id <= max; id++) {
272                     const void *tp = LCTF_INDEX_TO_TYPEPTR(fp, id);
273                     ctf_get_ctt_info(fp, tp, NULL, NULL, &isroot);
274                     if (isroot &&
275                         (rc = func(LCTF_INDEX_TO_TYPE(fp, id, child), arg)) != 0)
276                               return (rc);
277           }
278 
279           return (0);
280 }
281 
282 /*
283  * Follow a given type through the graph for TYPEDEF, VOLATILE, CONST, and
284  * RESTRICT nodes until we reach a "base" type node.  This is useful when
285  * we want to follow a type ID to a node that has members or a size.  To guard
286  * against infinite loops, we implement simplified cycle detection and check
287  * each link against itself, the previous node, and the topmost node.
288  */
289 ctf_id_t
ctf_type_resolve(ctf_file_t * fp,ctf_id_t type)290 ctf_type_resolve(ctf_file_t *fp, ctf_id_t type)
291 {
292           ctf_id_t prev = type, otype = type;
293           ctf_file_t *ofp = fp;
294           const void *tp;
295           uint_t kind, ctype;
296 
297           while ((tp = ctf_lookup_by_id(&fp, type)) != NULL) {
298                     ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
299                     switch (kind) {
300                     case CTF_K_TYPEDEF:
301                     case CTF_K_VOLATILE:
302                     case CTF_K_CONST:
303                     case CTF_K_RESTRICT:
304                               ctf_get_ctt_index(fp, tp, NULL, &ctype, NULL);
305                               if (ctype == type || ctype == otype || ctype == prev) {
306                                         ctf_dprintf("type %ld cycle detected\n", otype);
307                                         return (ctf_set_errno(ofp, ECTF_CORRUPT));
308                               }
309                               prev = type;
310                               type = ctype;
311                               break;
312                     default:
313                               return (type);
314                     }
315           }
316 
317           return (CTF_ERR); /* errno is set for us */
318 }
319 
320 /*
321  * Lookup the given type ID and print a string name for it into buf.  Return
322  * the actual number of bytes (not including \0) needed to format the name.
323  */
324 static ssize_t
ctf_type_qlname(ctf_file_t * fp,ctf_id_t type,char * buf,size_t len,const char * qname)325 ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
326     const char *qname)
327 {
328           ctf_decl_t cd;
329           ctf_decl_node_t *cdp;
330           ctf_decl_prec_t prec, lp, rp;
331           int ptr, arr;
332           uint_t k;
333 
334           if (fp == NULL && type == CTF_ERR)
335                     return (-1); /* simplify caller code by permitting CTF_ERR */
336 
337           ctf_decl_init(&cd, buf, len);
338           ctf_decl_push(&cd, fp, type);
339 
340           if (cd.cd_err != 0) {
341                     ctf_decl_fini(&cd);
342                     return (ctf_set_errno(fp, cd.cd_err));
343           }
344 
345           /*
346            * If the type graph's order conflicts with lexical precedence order
347            * for pointers or arrays, then we need to surround the declarations at
348            * the corresponding lexical precedence with parentheses.  This can
349            * result in either a parenthesized pointer (*) as in int (*)() or
350            * int (*)[], or in a parenthesized pointer and array as in int (*[])().
351            */
352           ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER;
353           arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY;
354 
355           rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1;
356           lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1;
357 
358           k = CTF_K_POINTER; /* avoid leading whitespace (see below) */
359 
360           for (prec = CTF_PREC_BASE; prec < CTF_PREC_MAX; prec++) {
361                     for (cdp = ctf_list_next(&cd.cd_nodes[prec]);
362                         cdp != NULL; cdp = ctf_list_next(cdp)) {
363 
364                               ctf_file_t *rfp = fp;
365                               const void *tp = ctf_lookup_by_id(&rfp, cdp->cd_type);
366                               const char *name = ctf_type_rname(rfp, tp);
367 
368                               if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
369                                         ctf_decl_sprintf(&cd, " ");
370 
371                               if (lp == prec) {
372                                         ctf_decl_sprintf(&cd, "(");
373                                         lp = -1;
374                               }
375 
376                               switch (cdp->cd_kind) {
377                               case CTF_K_INTEGER:
378                               case CTF_K_FLOAT:
379                               case CTF_K_TYPEDEF:
380                                         if (qname != NULL)
381                                                   ctf_decl_sprintf(&cd, "%s`", qname);
382                                         ctf_decl_sprintf(&cd, "%s", name);
383                                         break;
384                               case CTF_K_POINTER:
385                                         ctf_decl_sprintf(&cd, "*");
386                                         break;
387                               case CTF_K_ARRAY:
388                                         ctf_decl_sprintf(&cd, "[%u]", cdp->cd_n);
389                                         break;
390                               case CTF_K_FUNCTION:
391                                         ctf_decl_sprintf(&cd, "()");
392                                         break;
393                               case CTF_K_STRUCT:
394                               case CTF_K_FORWARD:
395                                         ctf_decl_sprintf(&cd, "struct ");
396                                         if (qname != NULL)
397                                                   ctf_decl_sprintf(&cd, "%s`", qname);
398                                         ctf_decl_sprintf(&cd, "%s", name);
399                                         break;
400                               case CTF_K_UNION:
401                                         ctf_decl_sprintf(&cd, "union ");
402                                         if (qname != NULL)
403                                                   ctf_decl_sprintf(&cd, "%s`", qname);
404                                         ctf_decl_sprintf(&cd, "%s", name);
405                                         break;
406                               case CTF_K_ENUM:
407                                         ctf_decl_sprintf(&cd, "enum ");
408                                         if (qname != NULL)
409                                                   ctf_decl_sprintf(&cd, "%s`", qname);
410                                         ctf_decl_sprintf(&cd, "%s", name);
411                                         break;
412                               case CTF_K_VOLATILE:
413                                         ctf_decl_sprintf(&cd, "volatile");
414                                         break;
415                               case CTF_K_CONST:
416                                         ctf_decl_sprintf(&cd, "const");
417                                         break;
418                               case CTF_K_RESTRICT:
419                                         ctf_decl_sprintf(&cd, "restrict");
420                                         break;
421                               }
422 
423                               k = cdp->cd_kind;
424                     }
425 
426                     if (rp == prec)
427                               ctf_decl_sprintf(&cd, ")");
428           }
429 
430           if (cd.cd_len >= len)
431                     (void) ctf_set_errno(fp, ECTF_NAMELEN);
432 
433           ctf_decl_fini(&cd);
434           return (cd.cd_len);
435 }
436 
437 ssize_t
ctf_type_lname(ctf_file_t * fp,ctf_id_t type,char * buf,size_t len)438 ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
439 {
440           return (ctf_type_qlname(fp, type, buf, len, NULL));
441 }
442 
443 /*
444  * Lookup the given type ID and print a string name for it into buf.  If buf
445  * is too small, return NULL: the ECTF_NAMELEN error is set on 'fp' for us.
446  */
447 char *
ctf_type_name(ctf_file_t * fp,ctf_id_t type,char * buf,size_t len)448 ctf_type_name(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
449 {
450           ssize_t rv = ctf_type_qlname(fp, type, buf, len, NULL);
451           return (rv >= 0 && rv < len ? buf : NULL);
452 }
453 
454 char *
ctf_type_qname(ctf_file_t * fp,ctf_id_t type,char * buf,size_t len,const char * qname)455 ctf_type_qname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
456     const char *qname)
457 {
458           ssize_t rv = ctf_type_qlname(fp, type, buf, len, qname);
459           return (rv >= 0 && rv < len ? buf : NULL);
460 }
461 
462 const char *
ctf_type_rname(ctf_file_t * fp,const void * v)463 ctf_type_rname(ctf_file_t *fp, const void *v)
464 {
465           uint_t name;
466 
467           if (fp->ctf_version == CTF_VERSION_2) {
468                     const struct ctf_type_v2 *ctt = v;
469 
470                     name = ctt->ctt_name;
471           } else {
472                     const struct ctf_type_v3 *ctt = v;
473 
474                     name = ctt->ctt_name;
475           }
476 
477           return (ctf_strptr(fp, name));
478 }
479 
480 /*
481  * Resolve the type down to a base type node, and then return the size
482  * of the type storage in bytes.
483  */
484 ssize_t
ctf_type_size(ctf_file_t * fp,ctf_id_t type)485 ctf_type_size(ctf_file_t *fp, ctf_id_t type)
486 {
487           const void *tp;
488           ssize_t size;
489           ctf_arinfo_t ar;
490           uint_t kind;
491 
492           if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
493                     return (-1); /* errno is set for us */
494 
495           if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
496                     return (-1); /* errno is set for us */
497 
498           ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
499 
500           switch (kind) {
501           case CTF_K_POINTER:
502                     return (fp->ctf_dmodel->ctd_pointer);
503 
504           case CTF_K_FUNCTION:
505                     return (0); /* function size is only known by symtab */
506 
507           case CTF_K_ENUM:
508                     return (fp->ctf_dmodel->ctd_int);
509 
510           case CTF_K_ARRAY:
511                     /*
512                      * Array size is not directly returned by stabs data.  Instead,
513                      * it defines the element type and requires the user to perform
514                      * the multiplication.  If ctf_get_ctt_size() returns zero, the
515                      * current version of ctfconvert does not compute member sizes
516                      * and we compute the size here on its behalf.
517                      */
518                     if ((size = ctf_get_ctt_size(fp, tp, NULL, NULL)) > 0)
519                               return (size);
520 
521                     if (ctf_array_info(fp, type, &ar) == CTF_ERR ||
522                         (size = ctf_type_size(fp, ar.ctr_contents)) == CTF_ERR)
523                               return (-1); /* errno is set for us */
524 
525                     return (size * ar.ctr_nelems);
526 
527           default:
528                     return (ctf_get_ctt_size(fp, tp, NULL, NULL));
529           }
530 }
531 
532 /*
533  * Resolve the type down to a base type node, and then return the alignment
534  * needed for the type storage in bytes.
535  */
536 ssize_t
ctf_type_align(ctf_file_t * fp,ctf_id_t type)537 ctf_type_align(ctf_file_t *fp, ctf_id_t type)
538 {
539           const void *tp;
540           ctf_arinfo_t r;
541           uint_t kind, vlen;
542 
543           if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
544                     return (-1); /* errno is set for us */
545 
546           if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
547                     return (-1); /* errno is set for us */
548 
549           ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
550 
551           switch (kind) {
552           case CTF_K_POINTER:
553           case CTF_K_FUNCTION:
554                     return (fp->ctf_dmodel->ctd_pointer);
555 
556           case CTF_K_ARRAY:
557                     if (ctf_array_info(fp, type, &r) == CTF_ERR)
558                               return (-1); /* errno is set for us */
559                     return (ctf_type_align(fp, r.ctr_contents));
560 
561           case CTF_K_STRUCT:
562           case CTF_K_UNION: {
563                     uint_t n = vlen;
564                     ssize_t size, increment;
565                     size_t align = 0;
566                     const void *vmp;
567 
568                     (void) ctf_get_ctt_size(fp, tp, &size, &increment);
569                     vmp = (const uchar_t *)tp + increment;
570 
571                     if (kind == CTF_K_STRUCT)
572                               n = MIN(n, 1); /* only use first member for structs */
573 
574                     for (const char *mp = vmp; n != 0; n--, mp += increment) {
575                               uint_t xtype;
576 
577                               ctf_get_ctm_info(fp, mp, size, &increment, &xtype,
578                                   NULL, NULL);
579                               ssize_t am = ctf_type_align(fp, xtype);
580                               align = MAX(align, am);
581                     }
582 
583                     return (align);
584           }
585 
586           case CTF_K_ENUM:
587                     return (fp->ctf_dmodel->ctd_int);
588 
589           default:
590                     return (ctf_get_ctt_size(fp, tp, NULL, NULL));
591           }
592 }
593 
594 /*
595  * Return the kind (CTF_K_* constant) for the specified type ID.
596  */
597 int
ctf_type_kind(ctf_file_t * fp,ctf_id_t type)598 ctf_type_kind(ctf_file_t *fp, ctf_id_t type)
599 {
600           const void *tp;
601           uint_t kind;
602 
603           if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
604                     return (CTF_ERR); /* errno is set for us */
605 
606           ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
607 
608           return (kind);
609 }
610 
611 /*
612  * If the type is one that directly references another type (such as POINTER),
613  * then return the ID of the type to which it refers.
614  */
615 ctf_id_t
ctf_type_reference(ctf_file_t * fp,ctf_id_t type)616 ctf_type_reference(ctf_file_t *fp, ctf_id_t type)
617 {
618           ctf_file_t *ofp = fp;
619           const void *tp;
620           uint_t ctype, kind;
621 
622           if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
623                     return (CTF_ERR); /* errno is set for us */
624 
625           ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
626 
627           switch (kind) {
628           case CTF_K_POINTER:
629           case CTF_K_TYPEDEF:
630           case CTF_K_VOLATILE:
631           case CTF_K_CONST:
632           case CTF_K_RESTRICT:
633                     ctf_get_ctt_index(fp, tp, NULL, &ctype, NULL);
634                     return (ctype);
635           default:
636                     return (ctf_set_errno(ofp, ECTF_NOTREF));
637           }
638 }
639 
640 /*
641  * Find a pointer to type by looking in fp->ctf_ptrtab.  If we can't find a
642  * pointer to the given type, see if we can compute a pointer to the type
643  * resulting from resolving the type down to its base type and use that
644  * instead.  This helps with cases where the CTF data includes "struct foo *"
645  * but not "foo_t *" and the user accesses "foo_t *" in the debugger.
646  */
647 ctf_id_t
ctf_type_pointer(ctf_file_t * fp,ctf_id_t type)648 ctf_type_pointer(ctf_file_t *fp, ctf_id_t type)
649 {
650           ctf_file_t *ofp = fp;
651           ctf_id_t ntype;
652 
653           if (ctf_lookup_by_id(&fp, type) == NULL)
654                     return (CTF_ERR); /* errno is set for us */
655 
656           if ((ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX(fp, type)]) != 0)
657                     return (LCTF_INDEX_TO_TYPE(fp, ntype, (fp->ctf_flags & LCTF_CHILD)));
658 
659           if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
660                     return (ctf_set_errno(ofp, ECTF_NOTYPE));
661 
662           if (ctf_lookup_by_id(&fp, type) == NULL)
663                     return (ctf_set_errno(ofp, ECTF_NOTYPE));
664 
665           if ((ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX(fp, type)]) != 0)
666                     return (LCTF_INDEX_TO_TYPE(fp, ntype, (fp->ctf_flags & LCTF_CHILD)));
667 
668           return (ctf_set_errno(ofp, ECTF_NOTYPE));
669 }
670 
671 /*
672  * Return the encoding for the specified INTEGER or FLOAT.
673  */
674 int
ctf_type_encoding(ctf_file_t * fp,ctf_id_t type,ctf_encoding_t * ep)675 ctf_type_encoding(ctf_file_t *fp, ctf_id_t type, ctf_encoding_t *ep)
676 {
677           ctf_file_t *ofp = fp;
678           const void *tp;
679           ssize_t increment;
680           uint_t data, kind;
681 
682           if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
683                     return (CTF_ERR); /* errno is set for us */
684 
685           (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
686           ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
687 
688           switch (kind) {
689           case CTF_K_INTEGER:
690                     data = *(const uint_t *)((uintptr_t)tp + increment);
691                     ep->cte_format = CTF_INT_ENCODING(data);
692                     ep->cte_offset = CTF_INT_OFFSET(data);
693                     ep->cte_bits = CTF_INT_BITS(data);
694                     break;
695           case CTF_K_FLOAT:
696                     data = *(const uint_t *)((uintptr_t)tp + increment);
697                     ep->cte_format = CTF_FP_ENCODING(data);
698                     ep->cte_offset = CTF_FP_OFFSET(data);
699                     ep->cte_bits = CTF_FP_BITS(data);
700                     break;
701           default:
702                     return (ctf_set_errno(ofp, ECTF_NOTINTFP));
703           }
704 
705           return (0);
706 }
707 
708 int
ctf_type_cmp(ctf_file_t * lfp,ctf_id_t ltype,ctf_file_t * rfp,ctf_id_t rtype)709 ctf_type_cmp(ctf_file_t *lfp, ctf_id_t ltype, ctf_file_t *rfp, ctf_id_t rtype)
710 {
711           int rval;
712 
713           if (ltype < rtype)
714                     rval = -1;
715           else if (ltype > rtype)
716                     rval = 1;
717           else
718                     rval = 0;
719 
720           if (lfp == rfp)
721                     return (rval);
722 
723           if (LCTF_TYPE_ISPARENT(lfp, ltype) && lfp->ctf_parent != NULL)
724                     lfp = lfp->ctf_parent;
725 
726           if (LCTF_TYPE_ISPARENT(rfp, rtype) && rfp->ctf_parent != NULL)
727                     rfp = rfp->ctf_parent;
728 
729           if (lfp < rfp)
730                     return (-1);
731 
732           if (lfp > rfp)
733                     return (1);
734 
735           return (rval);
736 }
737 
738 /*
739  * Return a boolean value indicating if two types are compatible integers or
740  * floating-pointer values.  This function returns true if the two types are
741  * the same, or if they have the same ASCII name and encoding properties.
742  * This function could be extended to test for compatibility for other kinds.
743  */
744 int
ctf_type_compat(ctf_file_t * lfp,ctf_id_t ltype,ctf_file_t * rfp,ctf_id_t rtype)745 ctf_type_compat(ctf_file_t *lfp, ctf_id_t ltype,
746     ctf_file_t *rfp, ctf_id_t rtype)
747 {
748           const void *ltp, *rtp;
749           ctf_encoding_t le, re;
750           ctf_arinfo_t la, ra;
751           uint_t lkind, rkind;
752 
753           if (ctf_type_cmp(lfp, ltype, rfp, rtype) == 0)
754                     return (1);
755 
756           ltype = ctf_type_resolve(lfp, ltype);
757           lkind = ctf_type_kind(lfp, ltype);
758 
759           rtype = ctf_type_resolve(rfp, rtype);
760           rkind = ctf_type_kind(rfp, rtype);
761 
762           if (lkind != rkind ||
763               (ltp = ctf_lookup_by_id(&lfp, ltype)) == NULL ||
764               (rtp = ctf_lookup_by_id(&rfp, rtype)) == NULL ||
765               strcmp(ctf_type_rname(lfp, ltp), ctf_type_rname(rfp, rtp)) != 0)
766                     return (0);
767 
768           switch (lkind) {
769           case CTF_K_INTEGER:
770           case CTF_K_FLOAT:
771                     return (ctf_type_encoding(lfp, ltype, &le) == 0 &&
772                         ctf_type_encoding(rfp, rtype, &re) == 0 &&
773                         memcmp(&le, &re, sizeof (ctf_encoding_t)) == 0);
774           case CTF_K_POINTER:
775                     return (ctf_type_compat(lfp, ctf_type_reference(lfp, ltype),
776                         rfp, ctf_type_reference(rfp, rtype)));
777           case CTF_K_ARRAY:
778                     return (ctf_array_info(lfp, ltype, &la) == 0 &&
779                         ctf_array_info(rfp, rtype, &ra) == 0 &&
780                         la.ctr_nelems == ra.ctr_nelems && ctf_type_compat(
781                         lfp, la.ctr_contents, rfp, ra.ctr_contents) &&
782                         ctf_type_compat(lfp, la.ctr_index, rfp, ra.ctr_index));
783           case CTF_K_STRUCT:
784           case CTF_K_UNION:
785                     return (ctf_type_size(lfp, ltype) == ctf_type_size(rfp, rtype));
786           case CTF_K_ENUM:
787           case CTF_K_FORWARD:
788                     return (1); /* no other checks required for these type kinds */
789           default:
790                     return (0); /* should not get here since we did a resolve */
791           }
792 }
793 
794 static int
_ctf_member_info(ctf_file_t * fp,ctf_id_t type,const char * name,ulong_t off,ctf_membinfo_t * mip)795 _ctf_member_info(ctf_file_t *fp, ctf_id_t type, const char *name, ulong_t off,
796     ctf_membinfo_t *mip)
797 {
798           ctf_file_t *ofp = fp;
799           const void *tp;
800           ssize_t size, increment;
801           uint_t kind, n, vlen;
802 
803           if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
804                     return (CTF_ERR); /* errno is set for us */
805 
806           if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
807                     return (CTF_ERR); /* errno is set for us */
808 
809           (void) ctf_get_ctt_size(fp, tp, &size, &increment);
810           ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
811 
812           if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
813                     return (ctf_set_errno(ofp, ECTF_NOTSOU));
814 
815           const char *mp = (const char *)((uintptr_t)tp + increment);
816 
817           for (n = vlen; n != 0; n--, mp += increment) {
818                     const char *name1;
819                     ulong_t offset;
820                     uint_t xtype;
821 
822                     ctf_get_ctm_info(fp, mp, size, &increment, &xtype, &offset,
823                         &name1);
824                     if (name1[0] == '\0' &&
825                         _ctf_member_info(fp, xtype, name, offset + off, mip) == 0)
826                               return (0);
827                     if (strcmp(name1, name) == 0) {
828                               mip->ctm_type = xtype;
829                               mip->ctm_offset = offset + off;
830                               return (0);
831                     }
832           }
833 
834           return (ctf_set_errno(ofp, ECTF_NOMEMBNAM));
835 }
836 
837 /*
838  * Return the type and offset for a given member of a STRUCT or UNION.
839  */
840 int
ctf_member_info(ctf_file_t * fp,ctf_id_t type,const char * name,ctf_membinfo_t * mip)841 ctf_member_info(ctf_file_t *fp, ctf_id_t type, const char *name,
842     ctf_membinfo_t *mip)
843 {
844 
845           return (_ctf_member_info(fp, type, name, 0, mip));
846 }
847 
848 /*
849  * Return the array type, index, and size information for the specified ARRAY.
850  */
851 int
ctf_array_info(ctf_file_t * fp,ctf_id_t type,ctf_arinfo_t * arp)852 ctf_array_info(ctf_file_t *fp, ctf_id_t type, ctf_arinfo_t *arp)
853 {
854           ctf_file_t *ofp = fp;
855           const void *ap, *tp;
856           ssize_t increment;
857           uint_t kind;
858 
859           if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
860                     return (CTF_ERR); /* errno is set for us */
861 
862           ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
863 
864           if (kind != CTF_K_ARRAY)
865                     return (ctf_set_errno(ofp, ECTF_NOTARRAY));
866 
867           (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
868 
869           ap = (const void *)((uintptr_t)tp + increment);
870           if (fp->ctf_version == CTF_VERSION_2) {
871                     const struct ctf_array_v2 *ap2 = ap;
872 
873                     arp->ctr_contents = ap2->cta_contents;
874                     arp->ctr_index = ap2->cta_index;
875                     arp->ctr_nelems = ap2->cta_nelems;
876           } else {
877                     const struct ctf_array_v3 *ap3 = ap;
878 
879                     arp->ctr_contents = ap3->cta_contents;
880                     arp->ctr_index = ap3->cta_index;
881                     arp->ctr_nelems = ap3->cta_nelems;
882           }
883 
884           return (0);
885 }
886 
887 /*
888  * Convert the specified value to the corresponding enum member name, if a
889  * matching name can be found.  Otherwise NULL is returned.
890  */
891 const char *
ctf_enum_name(ctf_file_t * fp,ctf_id_t type,int value)892 ctf_enum_name(ctf_file_t *fp, ctf_id_t type, int value)
893 {
894           ctf_file_t *ofp = fp;
895           const void *tp;
896           const ctf_enum_t *ep;
897           ssize_t increment;
898           uint_t kind, n, vlen;
899 
900           if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
901                     return (NULL); /* errno is set for us */
902 
903           if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
904                     return (NULL); /* errno is set for us */
905 
906           ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
907 
908           if (kind != CTF_K_ENUM) {
909                     (void) ctf_set_errno(ofp, ECTF_NOTENUM);
910                     return (NULL);
911           }
912 
913           (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
914 
915           ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
916 
917           for (n = vlen; n != 0; n--, ep++) {
918                     if (ep->cte_value == value)
919                               return (ctf_strptr(fp, ep->cte_name));
920           }
921 
922           (void) ctf_set_errno(ofp, ECTF_NOENUMNAM);
923           return (NULL);
924 }
925 
926 /*
927  * Convert the specified enum tag name to the corresponding value, if a
928  * matching name can be found.  Otherwise CTF_ERR is returned.
929  */
930 int
ctf_enum_value(ctf_file_t * fp,ctf_id_t type,const char * name,int * valp)931 ctf_enum_value(ctf_file_t *fp, ctf_id_t type, const char *name, int *valp)
932 {
933           ctf_file_t *ofp = fp;
934           const void *tp;
935           const ctf_enum_t *ep;
936           ssize_t size, increment;
937           uint_t kind, n, vlen;
938 
939           if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
940                     return (CTF_ERR); /* errno is set for us */
941 
942           if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
943                     return (CTF_ERR); /* errno is set for us */
944 
945           ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
946 
947           if (kind != CTF_K_ENUM) {
948                     (void) ctf_set_errno(ofp, ECTF_NOTENUM);
949                     return (CTF_ERR);
950           }
951 
952           (void) ctf_get_ctt_size(fp, tp, &size, &increment);
953 
954           ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
955 
956           for (n = vlen; n != 0; n--, ep++) {
957                     if (strcmp(ctf_strptr(fp, ep->cte_name), name) == 0) {
958                               if (valp != NULL)
959                                         *valp = ep->cte_value;
960                               return (0);
961                     }
962           }
963 
964           (void) ctf_set_errno(ofp, ECTF_NOENUMNAM);
965           return (CTF_ERR);
966 }
967 
968 /*
969  * Recursively visit the members of any type.  This function is used as the
970  * engine for ctf_type_visit, below.  We resolve the input type, recursively
971  * invoke ourself for each type member if the type is a struct or union, and
972  * then invoke the callback function on the current type.  If any callback
973  * returns non-zero, we abort and percolate the error code back up to the top.
974  */
975 static int
ctf_type_rvisit(ctf_file_t * fp,ctf_id_t type,ctf_visit_f * func,void * arg,const char * name,ulong_t offset,int depth)976 ctf_type_rvisit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg,
977     const char *name, ulong_t offset, int depth)
978 {
979           ctf_id_t otype = type;
980           const void *tp;
981           ssize_t size, increment;
982           uint_t kind, n, vlen;
983           int rc;
984 
985           if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
986                     return (CTF_ERR); /* errno is set for us */
987 
988           if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
989                     return (CTF_ERR); /* errno is set for us */
990 
991           if ((rc = func(name, otype, offset, depth, arg)) != 0)
992                     return (rc);
993 
994           ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
995 
996           if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
997                     return (0);
998 
999           (void) ctf_get_ctt_size(fp, tp, &size, &increment);
1000 
1001           const char *mp = (const char *)((uintptr_t)tp + increment);
1002           for (n = vlen; n != 0; n--, mp += increment) {
1003                     const char *xname;
1004                     ulong_t offset1;
1005                     uint_t xtype;
1006 
1007                     ctf_get_ctm_info(fp, mp, size, &increment, &xtype, &offset1,
1008                         &xname);
1009                     if ((rc = ctf_type_rvisit(fp, xtype, func, arg, xname,
1010                         offset + offset1, depth + 1)) != 0)
1011                               return (rc);
1012           }
1013 
1014           return (0);
1015 }
1016 
1017 /*
1018  * Recursively visit the members of any type.  We pass the name, member
1019  * type, and offset of each member to the specified callback function.
1020  */
1021 int
ctf_type_visit(ctf_file_t * fp,ctf_id_t type,ctf_visit_f * func,void * arg)1022 ctf_type_visit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg)
1023 {
1024           return (ctf_type_rvisit(fp, type, func, arg, "", 0, 0));
1025 }
1026