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