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