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