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