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 } 846