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