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