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