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 * Copyright 2020 Joyent, Inc. 29 */ 30 31 #include <ctf_impl.h> 32 #include <sys/debug.h> 33 34 ssize_t 35 ctf_get_ctt_size(const ctf_file_t *fp, const ctf_type_t *tp, ssize_t *sizep, 36 ssize_t *incrementp) 37 { 38 ssize_t size, increment; 39 40 if (fp->ctf_version > CTF_VERSION_1 && 41 tp->ctt_size == CTF_LSIZE_SENT) { 42 size = CTF_TYPE_LSIZE(tp); 43 increment = sizeof (ctf_type_t); 44 } else { 45 size = tp->ctt_size; 46 increment = sizeof (ctf_stype_t); 47 } 48 49 if (sizep) 50 *sizep = size; 51 if (incrementp) 52 *incrementp = increment; 53 54 return (size); 55 } 56 57 /* 58 * Iterate over the members of a STRUCT or UNION. We pass the name, member 59 * type, and offset of each member to the specified callback function. 60 */ 61 int 62 ctf_member_iter(ctf_file_t *fp, ctf_id_t type, ctf_member_f *func, void *arg) 63 { 64 ctf_file_t *ofp = fp; 65 const ctf_type_t *tp; 66 ssize_t size, increment; 67 uint_t kind, n; 68 int rc; 69 70 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR) 71 return (CTF_ERR); /* errno is set for us */ 72 73 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 74 return (CTF_ERR); /* errno is set for us */ 75 76 (void) ctf_get_ctt_size(fp, tp, &size, &increment); 77 kind = LCTF_INFO_KIND(fp, tp->ctt_info); 78 79 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) 80 return (ctf_set_errno(ofp, ECTF_NOTSOU)); 81 82 if (fp->ctf_version == CTF_VERSION_1 || size < CTF_LSTRUCT_THRESH) { 83 const ctf_member_t *mp = (const ctf_member_t *) 84 ((uintptr_t)tp + increment); 85 86 for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, mp++) { 87 const char *name = ctf_strptr(fp, mp->ctm_name); 88 if ((rc = func(name, mp->ctm_type, mp->ctm_offset, 89 arg)) != 0) 90 return (rc); 91 } 92 93 } else { 94 const ctf_lmember_t *lmp = (const ctf_lmember_t *) 95 ((uintptr_t)tp + increment); 96 97 for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, lmp++) { 98 const char *name = ctf_strptr(fp, lmp->ctlm_name); 99 if ((rc = func(name, lmp->ctlm_type, 100 (ulong_t)CTF_LMEM_OFFSET(lmp), arg)) != 0) 101 return (rc); 102 } 103 } 104 105 return (0); 106 } 107 108 /* 109 * Iterate over the members of an ENUM. We pass the string name and associated 110 * integer value of each enum element to the specified callback function. 111 */ 112 int 113 ctf_enum_iter(ctf_file_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg) 114 { 115 ctf_file_t *ofp = fp; 116 const ctf_type_t *tp; 117 const ctf_enum_t *ep; 118 ssize_t increment; 119 uint_t n; 120 int rc; 121 122 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR) 123 return (CTF_ERR); /* errno is set for us */ 124 125 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 126 return (CTF_ERR); /* errno is set for us */ 127 128 if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ENUM) 129 return (ctf_set_errno(ofp, ECTF_NOTENUM)); 130 131 (void) ctf_get_ctt_size(fp, tp, NULL, &increment); 132 133 ep = (const ctf_enum_t *)((uintptr_t)tp + increment); 134 135 for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, ep++) { 136 const char *name = ctf_strptr(fp, ep->cte_name); 137 if ((rc = func(name, ep->cte_value, arg)) != 0) 138 return (rc); 139 } 140 141 return (0); 142 } 143 144 /* 145 * Iterate over every type in the given CTF container. If the user doesn't ask 146 * for all types, then we only give them the user visible, aka root, types. We 147 * pass the type ID of each type to the specified callback function. 148 */ 149 int 150 ctf_type_iter(ctf_file_t *fp, boolean_t nonroot, ctf_type_f *func, void *arg) 151 { 152 ctf_id_t id, max = fp->ctf_typemax; 153 int rc, child = (fp->ctf_flags & LCTF_CHILD); 154 155 for (id = 1; id <= max; id++) { 156 const ctf_type_t *tp = LCTF_INDEX_TO_TYPEPTR(fp, id); 157 if ((nonroot || CTF_INFO_ISROOT(tp->ctt_info)) && 158 (rc = func(CTF_INDEX_TO_TYPE(id, child), 159 CTF_INFO_ISROOT(tp->ctt_info), arg)) != 0) 160 return (rc); 161 } 162 163 return (0); 164 } 165 166 /* 167 * Follow a given type through the graph for TYPEDEF, VOLATILE, CONST, and 168 * RESTRICT nodes until we reach a "base" type node. This is useful when 169 * we want to follow a type ID to a node that has members or a size. To guard 170 * against infinite loops, we implement simplified cycle detection and check 171 * each link against itself, the previous node, and the topmost node. 172 */ 173 ctf_id_t 174 ctf_type_resolve(ctf_file_t *fp, ctf_id_t type) 175 { 176 ctf_id_t prev = type, otype = type; 177 ctf_file_t *ofp = fp; 178 const ctf_type_t *tp; 179 180 while ((tp = ctf_lookup_by_id(&fp, type)) != NULL) { 181 switch (LCTF_INFO_KIND(fp, tp->ctt_info)) { 182 case CTF_K_TYPEDEF: 183 case CTF_K_VOLATILE: 184 case CTF_K_CONST: 185 case CTF_K_RESTRICT: 186 if (tp->ctt_type == type || tp->ctt_type == otype || 187 tp->ctt_type == prev) { 188 ctf_dprintf("type %ld cycle detected\n", otype); 189 return (ctf_set_errno(ofp, ECTF_CORRUPT)); 190 } 191 prev = type; 192 type = tp->ctt_type; 193 break; 194 default: 195 return (type); 196 } 197 } 198 199 return (CTF_ERR); /* errno is set for us */ 200 } 201 202 /* 203 * Format an integer type; if a vname is specified, we need to insert it prior 204 * to any bitfield ":24" suffix. This works out far simpler than figuring it 205 * out from scratch. 206 */ 207 static const char * 208 ctf_format_int(ctf_decl_t *cd, const char *vname, const char *qname, 209 const char *name) 210 { 211 const char *c; 212 213 if (vname == NULL) { 214 if (qname != NULL) 215 ctf_decl_sprintf(cd, "%s`%s", qname, name); 216 else 217 ctf_decl_sprintf(cd, "%s", name); 218 return (NULL); 219 } 220 221 if ((c = strchr(name, ':')) == NULL) { 222 ctf_decl_sprintf(cd, "%s", name); 223 return (vname); 224 } 225 226 /* "unsigned int mybits:23" */ 227 ctf_decl_sprintf(cd, "%.*s %s%s", c - name, name, vname, c); 228 return (NULL); 229 } 230 231 static void 232 ctf_format_func(ctf_file_t *fp, ctf_decl_t *cd, 233 const char *vname, ctf_id_t id, int want_func_args) 234 { 235 ctf_funcinfo_t fi; 236 /* We'll presume zone_create() is a bad example. */ 237 ctf_id_t args[20]; 238 239 ctf_decl_sprintf(cd, "%s(", vname == NULL ? "" : vname); 240 241 if (!want_func_args) 242 goto out; 243 244 if (ctf_func_info_by_id(fp, id, &fi) != 0) 245 goto out; 246 247 if (fi.ctc_argc > ARRAY_SIZE(args)) 248 fi.ctc_argc = ARRAY_SIZE(args); 249 250 if (fi.ctc_argc == 0) { 251 ctf_decl_sprintf(cd, "void"); 252 goto out; 253 } 254 255 if (ctf_func_args_by_id(fp, id, fi.ctc_argc, args) != 0) 256 goto out; 257 258 for (size_t i = 0; i < fi.ctc_argc; i++) { 259 char aname[512]; 260 261 if (ctf_type_name(fp, args[i], aname, sizeof (aname)) == NULL) 262 (void) strlcpy(aname, "unknown_t", sizeof (aname)); 263 264 ctf_decl_sprintf(cd, "%s%s", aname, 265 i + 1 == fi.ctc_argc ? "" : ", "); 266 } 267 268 if (fi.ctc_flags & CTF_FUNC_VARARG) 269 ctf_decl_sprintf(cd, "%s...", fi.ctc_argc == 0 ? "" : ", "); 270 271 out: 272 ctf_decl_sprintf(cd, ")"); 273 } 274 275 /* 276 * Lookup the given type ID and print a string name for it into buf. Return the 277 * actual number of bytes (not including \0) needed to format the name. 278 * 279 * "vname" is an optional variable name or similar, so array suffix formatting, 280 * bitfields, and functions are C-correct. (This is not perfect, as can be seen 281 * in kiconv_ops_t.) 282 */ 283 static ssize_t 284 ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len, 285 const char *vname, const char *qname) 286 { 287 int want_func_args = (vname != NULL); 288 ctf_decl_t cd; 289 ctf_decl_node_t *cdp; 290 ctf_decl_prec_t prec, lp, rp; 291 int ptr, arr; 292 uint_t k; 293 294 if (fp == NULL && type == CTF_ERR) 295 return (-1); /* simplify caller code by permitting CTF_ERR */ 296 297 ctf_decl_init(&cd, buf, len); 298 ctf_decl_push(&cd, fp, type); 299 300 if (cd.cd_err != 0) { 301 ctf_decl_fini(&cd); 302 return (ctf_set_errno(fp, cd.cd_err)); 303 } 304 305 /* 306 * If the type graph's order conflicts with lexical precedence order 307 * for pointers or arrays, then we need to surround the declarations at 308 * the corresponding lexical precedence with parentheses. This can 309 * result in either a parenthesized pointer (*) as in int (*)() or 310 * int (*)[], or in a parenthesized pointer and array as in int (*[])(). 311 */ 312 ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER; 313 arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY; 314 315 rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1; 316 lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1; 317 318 k = CTF_K_POINTER; /* avoid leading whitespace (see below) */ 319 320 for (prec = CTF_PREC_BASE; prec < CTF_PREC_MAX; prec++) { 321 for (cdp = ctf_list_next(&cd.cd_nodes[prec]); 322 cdp != NULL; cdp = ctf_list_next(cdp)) { 323 324 ctf_file_t *rfp = fp; 325 const ctf_type_t *tp = 326 ctf_lookup_by_id(&rfp, cdp->cd_type); 327 const char *name = ctf_strptr(rfp, tp->ctt_name); 328 329 if (k != CTF_K_POINTER && k != CTF_K_ARRAY) 330 ctf_decl_sprintf(&cd, " "); 331 332 if (lp == prec) { 333 ctf_decl_sprintf(&cd, "("); 334 lp = -1; 335 } 336 337 switch (cdp->cd_kind) { 338 case CTF_K_INTEGER: 339 vname = ctf_format_int(&cd, vname, qname, name); 340 break; 341 case CTF_K_FLOAT: 342 case CTF_K_TYPEDEF: 343 if (qname != NULL) 344 ctf_decl_sprintf(&cd, "%s`", qname); 345 ctf_decl_sprintf(&cd, "%s", name); 346 break; 347 case CTF_K_POINTER: 348 ctf_decl_sprintf(&cd, "*"); 349 break; 350 case CTF_K_ARRAY: 351 ctf_decl_sprintf(&cd, "%s[%u]", 352 vname != NULL ? vname : "", cdp->cd_n); 353 vname = NULL; 354 break; 355 case CTF_K_FUNCTION: 356 ctf_format_func(fp, &cd, vname, 357 cdp->cd_type, want_func_args); 358 vname = NULL; 359 break; 360 case CTF_K_STRUCT: 361 case CTF_K_FORWARD: 362 ctf_decl_sprintf(&cd, "struct "); 363 if (qname != NULL) 364 ctf_decl_sprintf(&cd, "%s`", qname); 365 ctf_decl_sprintf(&cd, "%s", name); 366 break; 367 case CTF_K_UNION: 368 ctf_decl_sprintf(&cd, "union "); 369 if (qname != NULL) 370 ctf_decl_sprintf(&cd, "%s`", qname); 371 ctf_decl_sprintf(&cd, "%s", name); 372 break; 373 case CTF_K_ENUM: 374 ctf_decl_sprintf(&cd, "enum "); 375 if (qname != NULL) 376 ctf_decl_sprintf(&cd, "%s`", qname); 377 ctf_decl_sprintf(&cd, "%s", name); 378 break; 379 case CTF_K_VOLATILE: 380 ctf_decl_sprintf(&cd, "volatile"); 381 break; 382 case CTF_K_CONST: 383 ctf_decl_sprintf(&cd, "const"); 384 break; 385 case CTF_K_RESTRICT: 386 ctf_decl_sprintf(&cd, "restrict"); 387 break; 388 } 389 390 k = cdp->cd_kind; 391 } 392 393 if (rp == prec) { 394 /* 395 * Peek ahead: if we're going to hit a function, 396 * we want to insert its name now before this closing 397 * bracket. 398 */ 399 if (vname != NULL && prec < CTF_PREC_FUNCTION) { 400 cdp = ctf_list_next( 401 &cd.cd_nodes[CTF_PREC_FUNCTION]); 402 403 if (cdp != NULL) { 404 ctf_decl_sprintf(&cd, "%s", vname); 405 vname = NULL; 406 } 407 } 408 409 ctf_decl_sprintf(&cd, ")"); 410 } 411 } 412 413 if (vname != NULL) 414 ctf_decl_sprintf(&cd, " %s", vname); 415 416 if (cd.cd_len >= len) 417 (void) ctf_set_errno(fp, ECTF_NAMELEN); 418 419 ctf_decl_fini(&cd); 420 return (cd.cd_len); 421 } 422 423 ssize_t 424 ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len) 425 { 426 return (ctf_type_qlname(fp, type, buf, len, NULL, NULL)); 427 } 428 429 /* 430 * Lookup the given type ID and print a string name for it into buf. If buf 431 * is too small, return NULL: the ECTF_NAMELEN error is set on 'fp' for us. 432 */ 433 char * 434 ctf_type_name(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len) 435 { 436 ssize_t rv = ctf_type_qlname(fp, type, buf, len, NULL, NULL); 437 return (rv >= 0 && rv < len ? buf : NULL); 438 } 439 440 char * 441 ctf_type_qname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len, 442 const char *qname) 443 { 444 ssize_t rv = ctf_type_qlname(fp, type, buf, len, NULL, qname); 445 return (rv >= 0 && rv < len ? buf : NULL); 446 } 447 448 char * 449 ctf_type_cname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len, 450 const char *cname) 451 { 452 ssize_t rv = ctf_type_qlname(fp, type, buf, len, cname, NULL); 453 return (rv >= 0 && rv < len ? buf : NULL); 454 } 455 456 /* 457 * Resolve the type down to a base type node, and then return the size 458 * of the type storage in bytes. 459 */ 460 ssize_t 461 ctf_type_size(ctf_file_t *fp, ctf_id_t type) 462 { 463 const ctf_type_t *tp; 464 ssize_t size; 465 ctf_arinfo_t ar; 466 467 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR) 468 return (-1); /* errno is set for us */ 469 470 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 471 return (-1); /* errno is set for us */ 472 473 switch (LCTF_INFO_KIND(fp, tp->ctt_info)) { 474 case CTF_K_POINTER: 475 return (fp->ctf_dmodel->ctd_pointer); 476 477 case CTF_K_FUNCTION: 478 return (0); /* function size is only known by symtab */ 479 480 case CTF_K_FORWARD: 481 return (0); 482 483 case CTF_K_ENUM: 484 return (ctf_get_ctt_size(fp, tp, NULL, NULL)); 485 486 case CTF_K_ARRAY: 487 /* 488 * Array size is not directly returned by stabs data. Instead, 489 * it defines the element type and requires the user to perform 490 * the multiplication. If ctf_get_ctt_size() returns zero, the 491 * current version of ctfconvert does not compute member sizes 492 * and we compute the size here on its behalf. 493 */ 494 if ((size = ctf_get_ctt_size(fp, tp, NULL, NULL)) > 0) 495 return (size); 496 497 if (ctf_array_info(fp, type, &ar) == CTF_ERR || 498 (size = ctf_type_size(fp, ar.ctr_contents)) == CTF_ERR) 499 return (-1); /* errno is set for us */ 500 501 return (size * ar.ctr_nelems); 502 case CTF_K_STRUCT: 503 case CTF_K_UNION: 504 /* 505 * If we have a zero size, we may be in the process of adding a 506 * structure or union but having not called ctf_update() to deal 507 * with the circular dependencies in such structures and unions. 508 * To handle that case, if we get a size of zero from the ctt, 509 * we look up the dtdef and use its size instead. 510 */ 511 size = ctf_get_ctt_size(fp, tp, NULL, NULL); 512 if (size == 0) { 513 ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, type); 514 if (dtd != NULL) 515 return (dtd->dtd_data.ctt_size); 516 } 517 return (size); 518 default: 519 return (ctf_get_ctt_size(fp, tp, NULL, NULL)); 520 } 521 } 522 523 /* 524 * Resolve the type down to a base type node, and then return the alignment 525 * needed for the type storage in bytes. 526 */ 527 ssize_t 528 ctf_type_align(ctf_file_t *fp, ctf_id_t type) 529 { 530 const ctf_type_t *tp; 531 ctf_arinfo_t r; 532 533 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR) 534 return (-1); /* errno is set for us */ 535 536 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 537 return (-1); /* errno is set for us */ 538 539 switch (LCTF_INFO_KIND(fp, tp->ctt_info)) { 540 case CTF_K_POINTER: 541 case CTF_K_FUNCTION: 542 return (fp->ctf_dmodel->ctd_pointer); 543 544 case CTF_K_ARRAY: 545 if (ctf_array_info(fp, type, &r) == CTF_ERR) 546 return (-1); /* errno is set for us */ 547 return (ctf_type_align(fp, r.ctr_contents)); 548 549 case CTF_K_STRUCT: 550 case CTF_K_UNION: { 551 uint_t n = LCTF_INFO_VLEN(fp, tp->ctt_info); 552 ssize_t size, increment; 553 size_t align = 0; 554 const void *vmp; 555 556 (void) ctf_get_ctt_size(fp, tp, &size, &increment); 557 vmp = (uchar_t *)tp + increment; 558 559 if (LCTF_INFO_KIND(fp, tp->ctt_info) == CTF_K_STRUCT) 560 n = MIN(n, 1); /* only use first member for structs */ 561 562 if (fp->ctf_version == CTF_VERSION_1 || 563 size < CTF_LSTRUCT_THRESH) { 564 const ctf_member_t *mp = vmp; 565 for (; n != 0; n--, mp++) { 566 ssize_t am = ctf_type_align(fp, mp->ctm_type); 567 align = MAX(align, am); 568 } 569 } else { 570 const ctf_lmember_t *lmp = vmp; 571 for (; n != 0; n--, lmp++) { 572 ssize_t am = ctf_type_align(fp, lmp->ctlm_type); 573 align = MAX(align, am); 574 } 575 } 576 577 return (align); 578 } 579 580 case CTF_K_ENUM: 581 default: 582 return (ctf_get_ctt_size(fp, tp, NULL, NULL)); 583 } 584 } 585 586 /* 587 * Return the kind (CTF_K_* constant) for the specified type ID. 588 */ 589 int 590 ctf_type_kind(ctf_file_t *fp, ctf_id_t type) 591 { 592 const ctf_type_t *tp; 593 594 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 595 return (CTF_ERR); /* errno is set for us */ 596 597 return (LCTF_INFO_KIND(fp, tp->ctt_info)); 598 } 599 600 /* 601 * If the type is one that directly references another type (such as POINTER), 602 * then return the ID of the type to which it refers. 603 */ 604 ctf_id_t 605 ctf_type_reference(ctf_file_t *fp, ctf_id_t type) 606 { 607 ctf_file_t *ofp = fp; 608 const ctf_type_t *tp; 609 610 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 611 return (CTF_ERR); /* errno is set for us */ 612 613 switch (LCTF_INFO_KIND(fp, tp->ctt_info)) { 614 case CTF_K_POINTER: 615 case CTF_K_TYPEDEF: 616 case CTF_K_VOLATILE: 617 case CTF_K_CONST: 618 case CTF_K_RESTRICT: 619 return (tp->ctt_type); 620 default: 621 return (ctf_set_errno(ofp, ECTF_NOTREF)); 622 } 623 } 624 625 /* 626 * Find a pointer to type by looking in fp->ctf_ptrtab. If we can't find a 627 * pointer to the given type, see if we can compute a pointer to the type 628 * resulting from resolving the type down to its base type and use that 629 * instead. This helps with cases where the CTF data includes "struct foo *" 630 * but not "foo_t *" and the user accesses "foo_t *" in the debugger. 631 */ 632 ctf_id_t 633 ctf_type_pointer(ctf_file_t *fp, ctf_id_t type) 634 { 635 ctf_file_t *ofp = fp; 636 ctf_id_t ntype; 637 638 if (ctf_lookup_by_id(&fp, type) == NULL) 639 return (CTF_ERR); /* errno is set for us */ 640 641 if ((ntype = fp->ctf_ptrtab[CTF_TYPE_TO_INDEX(type)]) != 0) 642 return (CTF_INDEX_TO_TYPE(ntype, (fp->ctf_flags & LCTF_CHILD))); 643 644 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR) 645 return (ctf_set_errno(ofp, ECTF_NOTYPE)); 646 647 if (ctf_lookup_by_id(&fp, type) == NULL) 648 return (ctf_set_errno(ofp, ECTF_NOTYPE)); 649 650 if ((ntype = fp->ctf_ptrtab[CTF_TYPE_TO_INDEX(type)]) != 0) 651 return (CTF_INDEX_TO_TYPE(ntype, (fp->ctf_flags & LCTF_CHILD))); 652 653 return (ctf_set_errno(ofp, ECTF_NOTYPE)); 654 } 655 656 /* 657 * Return the encoding for the specified INTEGER or FLOAT. 658 */ 659 int 660 ctf_type_encoding(ctf_file_t *fp, ctf_id_t type, ctf_encoding_t *ep) 661 { 662 ctf_file_t *ofp = fp; 663 const ctf_type_t *tp; 664 ssize_t increment; 665 uint_t data; 666 667 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 668 return (CTF_ERR); /* errno is set for us */ 669 670 (void) ctf_get_ctt_size(fp, tp, NULL, &increment); 671 672 switch (LCTF_INFO_KIND(fp, tp->ctt_info)) { 673 case CTF_K_INTEGER: 674 data = *(const uint_t *)((uintptr_t)tp + increment); 675 ep->cte_format = CTF_INT_ENCODING(data); 676 ep->cte_offset = CTF_INT_OFFSET(data); 677 ep->cte_bits = CTF_INT_BITS(data); 678 break; 679 case CTF_K_FLOAT: 680 data = *(const uint_t *)((uintptr_t)tp + increment); 681 ep->cte_format = CTF_FP_ENCODING(data); 682 ep->cte_offset = CTF_FP_OFFSET(data); 683 ep->cte_bits = CTF_FP_BITS(data); 684 break; 685 default: 686 return (ctf_set_errno(ofp, ECTF_NOTINTFP)); 687 } 688 689 return (0); 690 } 691 692 int 693 ctf_type_cmp(ctf_file_t *lfp, ctf_id_t ltype, ctf_file_t *rfp, ctf_id_t rtype) 694 { 695 int rval; 696 697 if (ltype < rtype) 698 rval = -1; 699 else if (ltype > rtype) 700 rval = 1; 701 else 702 rval = 0; 703 704 if (lfp == rfp) 705 return (rval); 706 707 if (CTF_TYPE_ISPARENT(ltype) && lfp->ctf_parent != NULL) 708 lfp = lfp->ctf_parent; 709 710 if (CTF_TYPE_ISPARENT(rtype) && rfp->ctf_parent != NULL) 711 rfp = rfp->ctf_parent; 712 713 if (lfp < rfp) 714 return (-1); 715 716 if (lfp > rfp) 717 return (1); 718 719 return (rval); 720 } 721 722 /* 723 * Return a boolean value indicating if two types are compatible integers or 724 * floating-pointer values. This function returns true if the two types are 725 * the same, or if they have the same ASCII name and encoding properties. 726 * This function could be extended to test for compatibility for other kinds. 727 */ 728 int 729 ctf_type_compat(ctf_file_t *lfp, ctf_id_t ltype, 730 ctf_file_t *rfp, ctf_id_t rtype) 731 { 732 const ctf_type_t *ltp, *rtp; 733 ctf_encoding_t le, re; 734 ctf_arinfo_t la, ra; 735 uint_t lkind, rkind; 736 737 if (ctf_type_cmp(lfp, ltype, rfp, rtype) == 0) 738 return (1); 739 740 ltype = ctf_type_resolve(lfp, ltype); 741 lkind = ctf_type_kind(lfp, ltype); 742 743 rtype = ctf_type_resolve(rfp, rtype); 744 rkind = ctf_type_kind(rfp, rtype); 745 746 if (lkind != rkind || 747 (ltp = ctf_lookup_by_id(&lfp, ltype)) == NULL || 748 (rtp = ctf_lookup_by_id(&rfp, rtype)) == NULL || 749 strcmp(ctf_strptr(lfp, ltp->ctt_name), 750 ctf_strptr(rfp, rtp->ctt_name)) != 0) 751 return (0); 752 753 switch (lkind) { 754 case CTF_K_INTEGER: 755 case CTF_K_FLOAT: 756 return (ctf_type_encoding(lfp, ltype, &le) == 0 && 757 ctf_type_encoding(rfp, rtype, &re) == 0 && 758 bcmp(&le, &re, sizeof (ctf_encoding_t)) == 0); 759 case CTF_K_POINTER: 760 return (ctf_type_compat(lfp, ctf_type_reference(lfp, ltype), 761 rfp, ctf_type_reference(rfp, rtype))); 762 case CTF_K_ARRAY: 763 return (ctf_array_info(lfp, ltype, &la) == 0 && 764 ctf_array_info(rfp, rtype, &ra) == 0 && 765 la.ctr_nelems == ra.ctr_nelems && ctf_type_compat( 766 lfp, la.ctr_contents, rfp, ra.ctr_contents) && 767 ctf_type_compat(lfp, la.ctr_index, rfp, ra.ctr_index)); 768 case CTF_K_STRUCT: 769 case CTF_K_UNION: 770 return (ctf_type_size(lfp, ltype) == ctf_type_size(rfp, rtype)); 771 case CTF_K_ENUM: 772 case CTF_K_FORWARD: 773 return (1); /* no other checks required for these type kinds */ 774 default: 775 return (0); /* should not get here since we did a resolve */ 776 } 777 } 778 779 /* 780 * Return the type and offset for a given member of a STRUCT or UNION. 781 */ 782 int 783 ctf_member_info(ctf_file_t *fp, ctf_id_t type, const char *name, 784 ctf_membinfo_t *mip) 785 { 786 ctf_file_t *ofp = fp; 787 const ctf_type_t *tp; 788 ssize_t size, increment; 789 uint_t kind, n; 790 791 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR) 792 return (CTF_ERR); /* errno is set for us */ 793 794 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 795 return (CTF_ERR); /* errno is set for us */ 796 797 (void) ctf_get_ctt_size(fp, tp, &size, &increment); 798 kind = LCTF_INFO_KIND(fp, tp->ctt_info); 799 800 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) 801 return (ctf_set_errno(ofp, ECTF_NOTSOU)); 802 803 if (fp->ctf_version == CTF_VERSION_1 || size < CTF_LSTRUCT_THRESH) { 804 const ctf_member_t *mp = (const ctf_member_t *) 805 ((uintptr_t)tp + increment); 806 807 for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, mp++) { 808 if (strcmp(ctf_strptr(fp, mp->ctm_name), name) == 0) { 809 mip->ctm_type = mp->ctm_type; 810 mip->ctm_offset = mp->ctm_offset; 811 return (0); 812 } 813 } 814 } else { 815 const ctf_lmember_t *lmp = (const ctf_lmember_t *) 816 ((uintptr_t)tp + increment); 817 818 for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, lmp++) { 819 if (strcmp(ctf_strptr(fp, lmp->ctlm_name), name) == 0) { 820 mip->ctm_type = lmp->ctlm_type; 821 mip->ctm_offset = (ulong_t)CTF_LMEM_OFFSET(lmp); 822 return (0); 823 } 824 } 825 } 826 827 return (ctf_set_errno(ofp, ECTF_NOMEMBNAM)); 828 } 829 830 /* 831 * Return the array type, index, and size information for the specified ARRAY. 832 */ 833 int 834 ctf_array_info(ctf_file_t *fp, ctf_id_t type, ctf_arinfo_t *arp) 835 { 836 ctf_file_t *ofp = fp; 837 const ctf_type_t *tp; 838 const ctf_array_t *ap; 839 ssize_t increment; 840 841 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 842 return (CTF_ERR); /* errno is set for us */ 843 844 if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ARRAY) 845 return (ctf_set_errno(ofp, ECTF_NOTARRAY)); 846 847 (void) ctf_get_ctt_size(fp, tp, NULL, &increment); 848 849 ap = (const ctf_array_t *)((uintptr_t)tp + increment); 850 arp->ctr_contents = ap->cta_contents; 851 arp->ctr_index = ap->cta_index; 852 arp->ctr_nelems = ap->cta_nelems; 853 854 return (0); 855 } 856 857 /* 858 * Convert the specified value to the corresponding enum member name, if a 859 * matching name can be found. Otherwise NULL is returned. 860 */ 861 const char * 862 ctf_enum_name(ctf_file_t *fp, ctf_id_t type, int value) 863 { 864 ctf_file_t *ofp = fp; 865 const ctf_type_t *tp; 866 const ctf_enum_t *ep; 867 ssize_t increment; 868 uint_t n; 869 870 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR) 871 return (NULL); /* errno is set for us */ 872 873 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 874 return (NULL); /* errno is set for us */ 875 876 if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ENUM) { 877 (void) ctf_set_errno(ofp, ECTF_NOTENUM); 878 return (NULL); 879 } 880 881 (void) ctf_get_ctt_size(fp, tp, NULL, &increment); 882 883 ep = (const ctf_enum_t *)((uintptr_t)tp + increment); 884 885 for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, ep++) { 886 if (ep->cte_value == value) 887 return (ctf_strptr(fp, ep->cte_name)); 888 } 889 890 (void) ctf_set_errno(ofp, ECTF_NOENUMNAM); 891 return (NULL); 892 } 893 894 /* 895 * Convert the specified enum tag name to the corresponding value, if a 896 * matching name can be found. Otherwise CTF_ERR is returned. 897 */ 898 int 899 ctf_enum_value(ctf_file_t *fp, ctf_id_t type, const char *name, int *valp) 900 { 901 ctf_file_t *ofp = fp; 902 const ctf_type_t *tp; 903 const ctf_enum_t *ep; 904 ssize_t size, increment; 905 uint_t n; 906 907 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR) 908 return (CTF_ERR); /* errno is set for us */ 909 910 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 911 return (CTF_ERR); /* errno is set for us */ 912 913 if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ENUM) { 914 (void) ctf_set_errno(ofp, ECTF_NOTENUM); 915 return (CTF_ERR); 916 } 917 918 (void) ctf_get_ctt_size(fp, tp, &size, &increment); 919 920 ep = (const ctf_enum_t *)((uintptr_t)tp + increment); 921 922 for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, ep++) { 923 if (strcmp(ctf_strptr(fp, ep->cte_name), name) == 0) { 924 if (valp != NULL) 925 *valp = ep->cte_value; 926 return (0); 927 } 928 } 929 930 (void) ctf_set_errno(ofp, ECTF_NOENUMNAM); 931 return (CTF_ERR); 932 } 933 934 /* 935 * Recursively visit the members of any type. This function is used as the 936 * engine for ctf_type_visit, below. We resolve the input type, recursively 937 * invoke ourself for each type member if the type is a struct or union, and 938 * then invoke the callback function on the current type. If any callback 939 * returns non-zero, we abort and percolate the error code back up to the top. 940 */ 941 static int 942 ctf_type_rvisit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg, 943 const char *name, ulong_t offset, int depth) 944 { 945 ctf_id_t otype = type; 946 const ctf_type_t *tp; 947 ssize_t size, increment; 948 uint_t kind, n; 949 int rc; 950 951 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR) 952 return (CTF_ERR); /* errno is set for us */ 953 954 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 955 return (CTF_ERR); /* errno is set for us */ 956 957 if ((rc = func(name, otype, offset, depth, arg)) != 0) 958 return (rc); 959 960 kind = LCTF_INFO_KIND(fp, tp->ctt_info); 961 962 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) 963 return (0); 964 965 (void) ctf_get_ctt_size(fp, tp, &size, &increment); 966 967 if (fp->ctf_version == CTF_VERSION_1 || size < CTF_LSTRUCT_THRESH) { 968 const ctf_member_t *mp = (const ctf_member_t *) 969 ((uintptr_t)tp + increment); 970 971 for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, mp++) { 972 if ((rc = ctf_type_rvisit(fp, mp->ctm_type, 973 func, arg, ctf_strptr(fp, mp->ctm_name), 974 offset + mp->ctm_offset, depth + 1)) != 0) 975 return (rc); 976 } 977 978 } else { 979 const ctf_lmember_t *lmp = (const ctf_lmember_t *) 980 ((uintptr_t)tp + increment); 981 982 for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, lmp++) { 983 if ((rc = ctf_type_rvisit(fp, lmp->ctlm_type, 984 func, arg, ctf_strptr(fp, lmp->ctlm_name), 985 offset + (ulong_t)CTF_LMEM_OFFSET(lmp), 986 depth + 1)) != 0) 987 return (rc); 988 } 989 } 990 991 return (0); 992 } 993 994 /* 995 * Recursively visit the members of any type. We pass the name, member 996 * type, and offset of each member to the specified callback function. 997 */ 998 int 999 ctf_type_visit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg) 1000 { 1001 return (ctf_type_rvisit(fp, type, func, arg, "", 0, 0)); 1002 } 1003 1004 int 1005 ctf_func_info_by_id(ctf_file_t *fp, ctf_id_t type, ctf_funcinfo_t *fip) 1006 { 1007 ctf_file_t *ofp = fp; 1008 const ctf_type_t *tp; 1009 const ushort_t *dp; 1010 int nargs; 1011 ssize_t increment; 1012 1013 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 1014 return (CTF_ERR); /* errno is set for us */ 1015 1016 if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_FUNCTION) 1017 return (ctf_set_errno(ofp, ECTF_NOTFUNC)); 1018 1019 fip->ctc_return = tp->ctt_type; 1020 nargs = LCTF_INFO_VLEN(fp, tp->ctt_info); 1021 fip->ctc_argc = nargs; 1022 fip->ctc_flags = 0; 1023 1024 /* dp should now point to the first argument */ 1025 if (nargs != 0) { 1026 (void) ctf_get_ctt_size(fp, tp, NULL, &increment); 1027 dp = (ushort_t *)((uintptr_t)fp->ctf_buf + 1028 fp->ctf_txlate[CTF_TYPE_TO_INDEX(type)] + increment); 1029 if (dp[nargs - 1] == 0) { 1030 fip->ctc_flags |= CTF_FUNC_VARARG; 1031 fip->ctc_argc--; 1032 } 1033 } 1034 1035 return (0); 1036 } 1037 1038 int 1039 ctf_func_args_by_id(ctf_file_t *fp, ctf_id_t type, uint_t argc, ctf_id_t *argv) 1040 { 1041 ctf_file_t *ofp = fp; 1042 const ctf_type_t *tp; 1043 const ushort_t *dp; 1044 int nargs; 1045 ssize_t increment; 1046 1047 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 1048 return (CTF_ERR); /* errno is set for us */ 1049 1050 if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_FUNCTION) 1051 return (ctf_set_errno(ofp, ECTF_NOTFUNC)); 1052 1053 nargs = LCTF_INFO_VLEN(fp, tp->ctt_info); 1054 (void) ctf_get_ctt_size(fp, tp, NULL, &increment); 1055 dp = (ushort_t *)((uintptr_t)fp->ctf_buf + 1056 fp->ctf_txlate[CTF_TYPE_TO_INDEX(type)] + 1057 increment); 1058 if (nargs != 0 && dp[nargs - 1] == 0) 1059 nargs--; 1060 1061 for (nargs = MIN(argc, nargs); nargs != 0; nargs--) 1062 *argv++ = *dp++; 1063 1064 return (0); 1065 } 1066 1067 int 1068 ctf_object_iter(ctf_file_t *fp, ctf_object_f *func, void *arg) 1069 { 1070 int i, ret; 1071 ctf_id_t id; 1072 uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data; 1073 uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data; 1074 1075 if (fp->ctf_symtab.cts_data == NULL) 1076 return (ctf_set_errno(fp, ECTF_NOSYMTAB)); 1077 1078 for (i = 0; i < fp->ctf_nsyms; i++) { 1079 char *name; 1080 if (fp->ctf_sxlate[i] == -1u) 1081 continue; 1082 id = *(ushort_t *)((uintptr_t)fp->ctf_buf + 1083 fp->ctf_sxlate[i]); 1084 1085 /* 1086 * Validate whether or not we're looking at a data object as 1087 * oposed to a function. 1088 */ 1089 if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) { 1090 const Elf32_Sym *symp = (Elf32_Sym *)symbase + i; 1091 if (ELF32_ST_TYPE(symp->st_info) != STT_OBJECT) 1092 continue; 1093 if (fp->ctf_strtab.cts_data != NULL && 1094 symp->st_name != 0) 1095 name = (char *)(strbase + symp->st_name); 1096 else 1097 name = NULL; 1098 } else { 1099 const Elf64_Sym *symp = (Elf64_Sym *)symbase + i; 1100 if (ELF64_ST_TYPE(symp->st_info) != STT_OBJECT) 1101 continue; 1102 if (fp->ctf_strtab.cts_data != NULL && 1103 symp->st_name != 0) 1104 name = (char *)(strbase + symp->st_name); 1105 else 1106 name = NULL; 1107 } 1108 1109 if ((ret = func(name, id, i, arg)) != 0) 1110 return (ret); 1111 } 1112 1113 return (0); 1114 } 1115 1116 int 1117 ctf_function_iter(ctf_file_t *fp, ctf_function_f *func, void *arg) 1118 { 1119 int i, ret; 1120 uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data; 1121 uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data; 1122 1123 if (fp->ctf_symtab.cts_data == NULL) 1124 return (ctf_set_errno(fp, ECTF_NOSYMTAB)); 1125 1126 for (i = 0; i < fp->ctf_nsyms; i++) { 1127 char *name; 1128 ushort_t info, *dp; 1129 ctf_funcinfo_t fi; 1130 if (fp->ctf_sxlate[i] == -1u) 1131 continue; 1132 1133 dp = (ushort_t *)((uintptr_t)fp->ctf_buf + 1134 fp->ctf_sxlate[i]); 1135 info = *dp; 1136 if (info == 0) 1137 continue; 1138 1139 /* 1140 * This may be a function or it may be a data object. We have to 1141 * consult the symbol table to be certain. Functions are encoded 1142 * with their info, data objects with their actual type. 1143 */ 1144 if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) { 1145 const Elf32_Sym *symp = (Elf32_Sym *)symbase + i; 1146 if (ELF32_ST_TYPE(symp->st_info) != STT_FUNC) 1147 continue; 1148 if (fp->ctf_strtab.cts_data != NULL) 1149 name = (char *)(strbase + symp->st_name); 1150 else 1151 name = NULL; 1152 } else { 1153 const Elf64_Sym *symp = (Elf64_Sym *)symbase + i; 1154 if (ELF64_ST_TYPE(symp->st_info) != STT_FUNC) 1155 continue; 1156 if (fp->ctf_strtab.cts_data != NULL) 1157 name = (char *)(strbase + symp->st_name); 1158 else 1159 name = NULL; 1160 } 1161 1162 if (LCTF_INFO_KIND(fp, info) != CTF_K_FUNCTION) 1163 continue; 1164 dp++; 1165 fi.ctc_return = *dp; 1166 dp++; 1167 fi.ctc_argc = LCTF_INFO_VLEN(fp, info); 1168 fi.ctc_flags = 0; 1169 1170 if (fi.ctc_argc != 0 && dp[fi.ctc_argc - 1] == 0) { 1171 fi.ctc_flags |= CTF_FUNC_VARARG; 1172 fi.ctc_argc--; 1173 } 1174 1175 if ((ret = func(name, i, &fi, arg)) != 0) 1176 return (ret); 1177 1178 } 1179 1180 return (0); 1181 } 1182 1183 char * 1184 ctf_symbol_name(ctf_file_t *fp, ulong_t idx, char *buf, size_t len) 1185 { 1186 const char *name; 1187 uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data; 1188 uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data; 1189 1190 if (fp->ctf_symtab.cts_data == NULL) { 1191 (void) ctf_set_errno(fp, ECTF_NOSYMTAB); 1192 return (NULL); 1193 } 1194 1195 if (fp->ctf_strtab.cts_data == NULL) { 1196 (void) ctf_set_errno(fp, ECTF_STRTAB); 1197 return (NULL); 1198 } 1199 1200 if (idx > fp->ctf_nsyms) { 1201 (void) ctf_set_errno(fp, ECTF_NOTDATA); 1202 return (NULL); 1203 } 1204 1205 if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) { 1206 const Elf32_Sym *symp = (Elf32_Sym *)symbase + idx; 1207 if (ELF32_ST_TYPE(symp->st_info) != STT_OBJECT && 1208 ELF32_ST_TYPE(symp->st_info) != STT_FUNC) { 1209 (void) ctf_set_errno(fp, ECTF_NOTDATA); 1210 return (NULL); 1211 } 1212 if (symp->st_name == 0) { 1213 (void) ctf_set_errno(fp, ENOENT); 1214 return (NULL); 1215 } 1216 name = (const char *)(strbase + symp->st_name); 1217 } else { 1218 const Elf64_Sym *symp = (Elf64_Sym *)symbase + idx; 1219 if (ELF64_ST_TYPE(symp->st_info) != STT_FUNC && 1220 ELF64_ST_TYPE(symp->st_info) != STT_OBJECT) { 1221 (void) ctf_set_errno(fp, ECTF_NOTDATA); 1222 return (NULL); 1223 } 1224 if (symp->st_name == 0) { 1225 (void) ctf_set_errno(fp, ENOENT); 1226 return (NULL); 1227 } 1228 name = (const char *)(strbase + symp->st_name); 1229 } 1230 1231 (void) strlcpy(buf, name, len); 1232 1233 return (buf); 1234 } 1235 1236 int 1237 ctf_string_iter(ctf_file_t *fp, ctf_string_f *func, void *arg) 1238 { 1239 int rc; 1240 const char *strp = fp->ctf_str[CTF_STRTAB_0].cts_strs; 1241 size_t strl = fp->ctf_str[CTF_STRTAB_0].cts_len; 1242 1243 while (strl > 0) { 1244 size_t len; 1245 1246 if ((rc = func(strp, arg)) != 0) 1247 return (rc); 1248 1249 len = strlen(strp) + 1; 1250 strl -= len; 1251 strp += len; 1252 } 1253 1254 return (0); 1255 } 1256 1257 /* 1258 * fp isn't strictly necessary at the moment. However, if we ever rev the file 1259 * format, the valid values for kind will change. 1260 */ 1261 const char * 1262 ctf_kind_name(ctf_file_t *fp, int kind) 1263 { 1264 switch (kind) { 1265 case CTF_K_INTEGER: 1266 return ("integer"); 1267 case CTF_K_FLOAT: 1268 return ("float"); 1269 case CTF_K_POINTER: 1270 return ("pointer"); 1271 case CTF_K_ARRAY: 1272 return ("array"); 1273 case CTF_K_FUNCTION: 1274 return ("function"); 1275 case CTF_K_STRUCT: 1276 return ("struct"); 1277 case CTF_K_UNION: 1278 return ("union"); 1279 case CTF_K_ENUM: 1280 return ("enum"); 1281 case CTF_K_FORWARD: 1282 return ("forward"); 1283 case CTF_K_TYPEDEF: 1284 return ("typedef"); 1285 case CTF_K_VOLATILE: 1286 return ("volatile"); 1287 case CTF_K_CONST: 1288 return ("const"); 1289 case CTF_K_RESTRICT: 1290 return ("restrict"); 1291 case CTF_K_UNKNOWN: 1292 default: 1293 return ("unknown"); 1294 } 1295 } 1296 1297 ctf_id_t 1298 ctf_max_id(ctf_file_t *fp) 1299 { 1300 int child = (fp->ctf_flags & LCTF_CHILD); 1301 return (fp->ctf_typemax + (child ? CTF_CHILD_START : 0)); 1302 } 1303 1304 ulong_t 1305 ctf_nr_syms(ctf_file_t *fp) 1306 { 1307 return (fp->ctf_nsyms); 1308 }