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