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 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 (fp->ctf_dmodel->ctd_int); 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 return (fp->ctf_dmodel->ctd_int); 582 583 default: 584 return (ctf_get_ctt_size(fp, tp, NULL, NULL)); 585 } 586 } 587 588 /* 589 * Return the kind (CTF_K_* constant) for the specified type ID. 590 */ 591 int 592 ctf_type_kind(ctf_file_t *fp, ctf_id_t type) 593 { 594 const ctf_type_t *tp; 595 596 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 597 return (CTF_ERR); /* errno is set for us */ 598 599 return (LCTF_INFO_KIND(fp, tp->ctt_info)); 600 } 601 602 /* 603 * If the type is one that directly references another type (such as POINTER), 604 * then return the ID of the type to which it refers. 605 */ 606 ctf_id_t 607 ctf_type_reference(ctf_file_t *fp, ctf_id_t type) 608 { 609 ctf_file_t *ofp = fp; 610 const ctf_type_t *tp; 611 612 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 613 return (CTF_ERR); /* errno is set for us */ 614 615 switch (LCTF_INFO_KIND(fp, tp->ctt_info)) { 616 case CTF_K_POINTER: 617 case CTF_K_TYPEDEF: 618 case CTF_K_VOLATILE: 619 case CTF_K_CONST: 620 case CTF_K_RESTRICT: 621 return (tp->ctt_type); 622 default: 623 return (ctf_set_errno(ofp, ECTF_NOTREF)); 624 } 625 } 626 627 /* 628 * Find a pointer to type by looking in fp->ctf_ptrtab. If we can't find a 629 * pointer to the given type, see if we can compute a pointer to the type 630 * resulting from resolving the type down to its base type and use that 631 * instead. This helps with cases where the CTF data includes "struct foo *" 632 * but not "foo_t *" and the user accesses "foo_t *" in the debugger. 633 */ 634 ctf_id_t 635 ctf_type_pointer(ctf_file_t *fp, ctf_id_t type) 636 { 637 ctf_file_t *ofp = fp; 638 ctf_id_t ntype; 639 640 if (ctf_lookup_by_id(&fp, type) == NULL) 641 return (CTF_ERR); /* errno is set for us */ 642 643 if ((ntype = fp->ctf_ptrtab[CTF_TYPE_TO_INDEX(type)]) != 0) 644 return (CTF_INDEX_TO_TYPE(ntype, (fp->ctf_flags & LCTF_CHILD))); 645 646 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR) 647 return (ctf_set_errno(ofp, ECTF_NOTYPE)); 648 649 if (ctf_lookup_by_id(&fp, type) == NULL) 650 return (ctf_set_errno(ofp, ECTF_NOTYPE)); 651 652 if ((ntype = fp->ctf_ptrtab[CTF_TYPE_TO_INDEX(type)]) != 0) 653 return (CTF_INDEX_TO_TYPE(ntype, (fp->ctf_flags & LCTF_CHILD))); 654 655 return (ctf_set_errno(ofp, ECTF_NOTYPE)); 656 } 657 658 /* 659 * Return the encoding for the specified INTEGER or FLOAT. 660 */ 661 int 662 ctf_type_encoding(ctf_file_t *fp, ctf_id_t type, ctf_encoding_t *ep) 663 { 664 ctf_file_t *ofp = fp; 665 const ctf_type_t *tp; 666 ssize_t increment; 667 uint_t data; 668 669 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 670 return (CTF_ERR); /* errno is set for us */ 671 672 (void) ctf_get_ctt_size(fp, tp, NULL, &increment); 673 674 switch (LCTF_INFO_KIND(fp, tp->ctt_info)) { 675 case CTF_K_INTEGER: 676 data = *(const uint_t *)((uintptr_t)tp + increment); 677 ep->cte_format = CTF_INT_ENCODING(data); 678 ep->cte_offset = CTF_INT_OFFSET(data); 679 ep->cte_bits = CTF_INT_BITS(data); 680 break; 681 case CTF_K_FLOAT: 682 data = *(const uint_t *)((uintptr_t)tp + increment); 683 ep->cte_format = CTF_FP_ENCODING(data); 684 ep->cte_offset = CTF_FP_OFFSET(data); 685 ep->cte_bits = CTF_FP_BITS(data); 686 break; 687 default: 688 return (ctf_set_errno(ofp, ECTF_NOTINTFP)); 689 } 690 691 return (0); 692 } 693 694 int 695 ctf_type_cmp(ctf_file_t *lfp, ctf_id_t ltype, ctf_file_t *rfp, ctf_id_t rtype) 696 { 697 int rval; 698 699 if (ltype < rtype) 700 rval = -1; 701 else if (ltype > rtype) 702 rval = 1; 703 else 704 rval = 0; 705 706 if (lfp == rfp) 707 return (rval); 708 709 if (CTF_TYPE_ISPARENT(ltype) && lfp->ctf_parent != NULL) 710 lfp = lfp->ctf_parent; 711 712 if (CTF_TYPE_ISPARENT(rtype) && rfp->ctf_parent != NULL) 713 rfp = rfp->ctf_parent; 714 715 if (lfp < rfp) 716 return (-1); 717 718 if (lfp > rfp) 719 return (1); 720 721 return (rval); 722 } 723 724 /* 725 * Return a boolean value indicating if two types are compatible integers or 726 * floating-pointer values. This function returns true if the two types are 727 * the same, or if they have the same ASCII name and encoding properties. 728 * This function could be extended to test for compatibility for other kinds. 729 */ 730 int 731 ctf_type_compat(ctf_file_t *lfp, ctf_id_t ltype, 732 ctf_file_t *rfp, ctf_id_t rtype) 733 { 734 const ctf_type_t *ltp, *rtp; 735 ctf_encoding_t le, re; 736 ctf_arinfo_t la, ra; 737 uint_t lkind, rkind; 738 739 if (ctf_type_cmp(lfp, ltype, rfp, rtype) == 0) 740 return (1); 741 742 ltype = ctf_type_resolve(lfp, ltype); 743 lkind = ctf_type_kind(lfp, ltype); 744 745 rtype = ctf_type_resolve(rfp, rtype); 746 rkind = ctf_type_kind(rfp, rtype); 747 748 if (lkind != rkind || 749 (ltp = ctf_lookup_by_id(&lfp, ltype)) == NULL || 750 (rtp = ctf_lookup_by_id(&rfp, rtype)) == NULL || 751 strcmp(ctf_strptr(lfp, ltp->ctt_name), 752 ctf_strptr(rfp, rtp->ctt_name)) != 0) 753 return (0); 754 755 switch (lkind) { 756 case CTF_K_INTEGER: 757 case CTF_K_FLOAT: 758 return (ctf_type_encoding(lfp, ltype, &le) == 0 && 759 ctf_type_encoding(rfp, rtype, &re) == 0 && 760 bcmp(&le, &re, sizeof (ctf_encoding_t)) == 0); 761 case CTF_K_POINTER: 762 return (ctf_type_compat(lfp, ctf_type_reference(lfp, ltype), 763 rfp, ctf_type_reference(rfp, rtype))); 764 case CTF_K_ARRAY: 765 return (ctf_array_info(lfp, ltype, &la) == 0 && 766 ctf_array_info(rfp, rtype, &ra) == 0 && 767 la.ctr_nelems == ra.ctr_nelems && ctf_type_compat( 768 lfp, la.ctr_contents, rfp, ra.ctr_contents) && 769 ctf_type_compat(lfp, la.ctr_index, rfp, ra.ctr_index)); 770 case CTF_K_STRUCT: 771 case CTF_K_UNION: 772 return (ctf_type_size(lfp, ltype) == ctf_type_size(rfp, rtype)); 773 case CTF_K_ENUM: 774 case CTF_K_FORWARD: 775 return (1); /* no other checks required for these type kinds */ 776 default: 777 return (0); /* should not get here since we did a resolve */ 778 } 779 } 780 781 /* 782 * Return the type and offset for a given member of a STRUCT or UNION. 783 */ 784 int 785 ctf_member_info(ctf_file_t *fp, ctf_id_t type, const char *name, 786 ctf_membinfo_t *mip) 787 { 788 ctf_file_t *ofp = fp; 789 const ctf_type_t *tp; 790 ssize_t size, increment; 791 uint_t kind, n; 792 793 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR) 794 return (CTF_ERR); /* errno is set for us */ 795 796 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 797 return (CTF_ERR); /* errno is set for us */ 798 799 (void) ctf_get_ctt_size(fp, tp, &size, &increment); 800 kind = LCTF_INFO_KIND(fp, tp->ctt_info); 801 802 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) 803 return (ctf_set_errno(ofp, ECTF_NOTSOU)); 804 805 if (fp->ctf_version == CTF_VERSION_1 || size < CTF_LSTRUCT_THRESH) { 806 const ctf_member_t *mp = (const ctf_member_t *) 807 ((uintptr_t)tp + increment); 808 809 for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, mp++) { 810 if (strcmp(ctf_strptr(fp, mp->ctm_name), name) == 0) { 811 mip->ctm_type = mp->ctm_type; 812 mip->ctm_offset = mp->ctm_offset; 813 return (0); 814 } 815 } 816 } else { 817 const ctf_lmember_t *lmp = (const ctf_lmember_t *) 818 ((uintptr_t)tp + increment); 819 820 for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, lmp++) { 821 if (strcmp(ctf_strptr(fp, lmp->ctlm_name), name) == 0) { 822 mip->ctm_type = lmp->ctlm_type; 823 mip->ctm_offset = (ulong_t)CTF_LMEM_OFFSET(lmp); 824 return (0); 825 } 826 } 827 } 828 829 return (ctf_set_errno(ofp, ECTF_NOMEMBNAM)); 830 } 831 832 /* 833 * Return the array type, index, and size information for the specified ARRAY. 834 */ 835 int 836 ctf_array_info(ctf_file_t *fp, ctf_id_t type, ctf_arinfo_t *arp) 837 { 838 ctf_file_t *ofp = fp; 839 const ctf_type_t *tp; 840 const ctf_array_t *ap; 841 ssize_t increment; 842 843 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 844 return (CTF_ERR); /* errno is set for us */ 845 846 if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ARRAY) 847 return (ctf_set_errno(ofp, ECTF_NOTARRAY)); 848 849 (void) ctf_get_ctt_size(fp, tp, NULL, &increment); 850 851 ap = (const ctf_array_t *)((uintptr_t)tp + increment); 852 arp->ctr_contents = ap->cta_contents; 853 arp->ctr_index = ap->cta_index; 854 arp->ctr_nelems = ap->cta_nelems; 855 856 return (0); 857 } 858 859 /* 860 * Convert the specified value to the corresponding enum member name, if a 861 * matching name can be found. Otherwise NULL is returned. 862 */ 863 const char * 864 ctf_enum_name(ctf_file_t *fp, ctf_id_t type, int value) 865 { 866 ctf_file_t *ofp = fp; 867 const ctf_type_t *tp; 868 const ctf_enum_t *ep; 869 ssize_t increment; 870 uint_t n; 871 872 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR) 873 return (NULL); /* errno is set for us */ 874 875 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 876 return (NULL); /* errno is set for us */ 877 878 if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ENUM) { 879 (void) ctf_set_errno(ofp, ECTF_NOTENUM); 880 return (NULL); 881 } 882 883 (void) ctf_get_ctt_size(fp, tp, NULL, &increment); 884 885 ep = (const ctf_enum_t *)((uintptr_t)tp + increment); 886 887 for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, ep++) { 888 if (ep->cte_value == value) 889 return (ctf_strptr(fp, ep->cte_name)); 890 } 891 892 (void) ctf_set_errno(ofp, ECTF_NOENUMNAM); 893 return (NULL); 894 } 895 896 /* 897 * Convert the specified enum tag name to the corresponding value, if a 898 * matching name can be found. Otherwise CTF_ERR is returned. 899 */ 900 int 901 ctf_enum_value(ctf_file_t *fp, ctf_id_t type, const char *name, int *valp) 902 { 903 ctf_file_t *ofp = fp; 904 const ctf_type_t *tp; 905 const ctf_enum_t *ep; 906 ssize_t size, increment; 907 uint_t n; 908 909 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR) 910 return (CTF_ERR); /* errno is set for us */ 911 912 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 913 return (CTF_ERR); /* errno is set for us */ 914 915 if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ENUM) { 916 (void) ctf_set_errno(ofp, ECTF_NOTENUM); 917 return (CTF_ERR); 918 } 919 920 (void) ctf_get_ctt_size(fp, tp, &size, &increment); 921 922 ep = (const ctf_enum_t *)((uintptr_t)tp + increment); 923 924 for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, ep++) { 925 if (strcmp(ctf_strptr(fp, ep->cte_name), name) == 0) { 926 if (valp != NULL) 927 *valp = ep->cte_value; 928 return (0); 929 } 930 } 931 932 (void) ctf_set_errno(ofp, ECTF_NOENUMNAM); 933 return (CTF_ERR); 934 } 935 936 /* 937 * Recursively visit the members of any type. This function is used as the 938 * engine for ctf_type_visit, below. We resolve the input type, recursively 939 * invoke ourself for each type member if the type is a struct or union, and 940 * then invoke the callback function on the current type. If any callback 941 * returns non-zero, we abort and percolate the error code back up to the top. 942 */ 943 static int 944 ctf_type_rvisit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg, 945 const char *name, ulong_t offset, int depth) 946 { 947 ctf_id_t otype = type; 948 const ctf_type_t *tp; 949 ssize_t size, increment; 950 uint_t kind, n; 951 int rc; 952 953 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR) 954 return (CTF_ERR); /* errno is set for us */ 955 956 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 957 return (CTF_ERR); /* errno is set for us */ 958 959 if ((rc = func(name, otype, offset, depth, arg)) != 0) 960 return (rc); 961 962 kind = LCTF_INFO_KIND(fp, tp->ctt_info); 963 964 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) 965 return (0); 966 967 (void) ctf_get_ctt_size(fp, tp, &size, &increment); 968 969 if (fp->ctf_version == CTF_VERSION_1 || size < CTF_LSTRUCT_THRESH) { 970 const ctf_member_t *mp = (const ctf_member_t *) 971 ((uintptr_t)tp + increment); 972 973 for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, mp++) { 974 if ((rc = ctf_type_rvisit(fp, mp->ctm_type, 975 func, arg, ctf_strptr(fp, mp->ctm_name), 976 offset + mp->ctm_offset, depth + 1)) != 0) 977 return (rc); 978 } 979 980 } else { 981 const ctf_lmember_t *lmp = (const ctf_lmember_t *) 982 ((uintptr_t)tp + increment); 983 984 for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, lmp++) { 985 if ((rc = ctf_type_rvisit(fp, lmp->ctlm_type, 986 func, arg, ctf_strptr(fp, lmp->ctlm_name), 987 offset + (ulong_t)CTF_LMEM_OFFSET(lmp), 988 depth + 1)) != 0) 989 return (rc); 990 } 991 } 992 993 return (0); 994 } 995 996 /* 997 * Recursively visit the members of any type. We pass the name, member 998 * type, and offset of each member to the specified callback function. 999 */ 1000 int 1001 ctf_type_visit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg) 1002 { 1003 return (ctf_type_rvisit(fp, type, func, arg, "", 0, 0)); 1004 } 1005 1006 int 1007 ctf_func_info_by_id(ctf_file_t *fp, ctf_id_t type, ctf_funcinfo_t *fip) 1008 { 1009 ctf_file_t *ofp = fp; 1010 const ctf_type_t *tp; 1011 const ushort_t *dp; 1012 int nargs; 1013 ssize_t increment; 1014 1015 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 1016 return (CTF_ERR); /* errno is set for us */ 1017 1018 if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_FUNCTION) 1019 return (ctf_set_errno(ofp, ECTF_NOTFUNC)); 1020 1021 fip->ctc_return = tp->ctt_type; 1022 nargs = LCTF_INFO_VLEN(fp, tp->ctt_info); 1023 fip->ctc_argc = nargs; 1024 fip->ctc_flags = 0; 1025 1026 /* dp should now point to the first argument */ 1027 if (nargs != 0) { 1028 (void) ctf_get_ctt_size(fp, tp, NULL, &increment); 1029 dp = (ushort_t *)((uintptr_t)fp->ctf_buf + 1030 fp->ctf_txlate[CTF_TYPE_TO_INDEX(type)] + increment); 1031 if (dp[nargs - 1] == 0) { 1032 fip->ctc_flags |= CTF_FUNC_VARARG; 1033 fip->ctc_argc--; 1034 } 1035 } 1036 1037 return (0); 1038 } 1039 1040 int 1041 ctf_func_args_by_id(ctf_file_t *fp, ctf_id_t type, uint_t argc, ctf_id_t *argv) 1042 { 1043 ctf_file_t *ofp = fp; 1044 const ctf_type_t *tp; 1045 const ushort_t *dp; 1046 int nargs; 1047 ssize_t increment; 1048 1049 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) 1050 return (CTF_ERR); /* errno is set for us */ 1051 1052 if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_FUNCTION) 1053 return (ctf_set_errno(ofp, ECTF_NOTFUNC)); 1054 1055 nargs = LCTF_INFO_VLEN(fp, tp->ctt_info); 1056 (void) ctf_get_ctt_size(fp, tp, NULL, &increment); 1057 dp = (ushort_t *)((uintptr_t)fp->ctf_buf + 1058 fp->ctf_txlate[CTF_TYPE_TO_INDEX(type)] + 1059 increment); 1060 if (nargs != 0 && dp[nargs - 1] == 0) 1061 nargs--; 1062 1063 for (nargs = MIN(argc, nargs); nargs != 0; nargs--) 1064 *argv++ = *dp++; 1065 1066 return (0); 1067 } 1068 1069 int 1070 ctf_object_iter(ctf_file_t *fp, ctf_object_f *func, void *arg) 1071 { 1072 int i, ret; 1073 ctf_id_t id; 1074 uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data; 1075 uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data; 1076 1077 if (fp->ctf_symtab.cts_data == NULL) 1078 return (ctf_set_errno(fp, ECTF_NOSYMTAB)); 1079 1080 for (i = 0; i < fp->ctf_nsyms; i++) { 1081 char *name; 1082 if (fp->ctf_sxlate[i] == -1u) 1083 continue; 1084 id = *(ushort_t *)((uintptr_t)fp->ctf_buf + 1085 fp->ctf_sxlate[i]); 1086 1087 /* 1088 * Validate whether or not we're looking at a data object as 1089 * oposed to a function. 1090 */ 1091 if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) { 1092 const Elf32_Sym *symp = (Elf32_Sym *)symbase + i; 1093 if (ELF32_ST_TYPE(symp->st_info) != STT_OBJECT) 1094 continue; 1095 if (fp->ctf_strtab.cts_data != NULL && 1096 symp->st_name != 0) 1097 name = (char *)(strbase + symp->st_name); 1098 else 1099 name = NULL; 1100 } else { 1101 const Elf64_Sym *symp = (Elf64_Sym *)symbase + i; 1102 if (ELF64_ST_TYPE(symp->st_info) != STT_OBJECT) 1103 continue; 1104 if (fp->ctf_strtab.cts_data != NULL && 1105 symp->st_name != 0) 1106 name = (char *)(strbase + symp->st_name); 1107 else 1108 name = NULL; 1109 } 1110 1111 if ((ret = func(name, id, i, arg)) != 0) 1112 return (ret); 1113 } 1114 1115 return (0); 1116 } 1117 1118 int 1119 ctf_function_iter(ctf_file_t *fp, ctf_function_f *func, void *arg) 1120 { 1121 int i, ret; 1122 uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data; 1123 uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data; 1124 1125 if (fp->ctf_symtab.cts_data == NULL) 1126 return (ctf_set_errno(fp, ECTF_NOSYMTAB)); 1127 1128 for (i = 0; i < fp->ctf_nsyms; i++) { 1129 char *name; 1130 ushort_t info, *dp; 1131 ctf_funcinfo_t fi; 1132 if (fp->ctf_sxlate[i] == -1u) 1133 continue; 1134 1135 dp = (ushort_t *)((uintptr_t)fp->ctf_buf + 1136 fp->ctf_sxlate[i]); 1137 info = *dp; 1138 if (info == 0) 1139 continue; 1140 1141 /* 1142 * This may be a function or it may be a data object. We have to 1143 * consult the symbol table to be certain. Functions are encoded 1144 * with their info, data objects with their actual type. 1145 */ 1146 if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) { 1147 const Elf32_Sym *symp = (Elf32_Sym *)symbase + i; 1148 if (ELF32_ST_TYPE(symp->st_info) != STT_FUNC) 1149 continue; 1150 if (fp->ctf_strtab.cts_data != NULL) 1151 name = (char *)(strbase + symp->st_name); 1152 else 1153 name = NULL; 1154 } else { 1155 const Elf64_Sym *symp = (Elf64_Sym *)symbase + i; 1156 if (ELF64_ST_TYPE(symp->st_info) != STT_FUNC) 1157 continue; 1158 if (fp->ctf_strtab.cts_data != NULL) 1159 name = (char *)(strbase + symp->st_name); 1160 else 1161 name = NULL; 1162 } 1163 1164 if (LCTF_INFO_KIND(fp, info) != CTF_K_FUNCTION) 1165 continue; 1166 dp++; 1167 fi.ctc_return = *dp; 1168 dp++; 1169 fi.ctc_argc = LCTF_INFO_VLEN(fp, info); 1170 fi.ctc_flags = 0; 1171 1172 if (fi.ctc_argc != 0 && dp[fi.ctc_argc - 1] == 0) { 1173 fi.ctc_flags |= CTF_FUNC_VARARG; 1174 fi.ctc_argc--; 1175 } 1176 1177 if ((ret = func(name, i, &fi, arg)) != 0) 1178 return (ret); 1179 1180 } 1181 1182 return (0); 1183 } 1184 1185 char * 1186 ctf_symbol_name(ctf_file_t *fp, ulong_t idx, char *buf, size_t len) 1187 { 1188 const char *name; 1189 uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data; 1190 uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data; 1191 1192 if (fp->ctf_symtab.cts_data == NULL) { 1193 (void) ctf_set_errno(fp, ECTF_NOSYMTAB); 1194 return (NULL); 1195 } 1196 1197 if (fp->ctf_strtab.cts_data == NULL) { 1198 (void) ctf_set_errno(fp, ECTF_STRTAB); 1199 return (NULL); 1200 } 1201 1202 if (idx > fp->ctf_nsyms) { 1203 (void) ctf_set_errno(fp, ECTF_NOTDATA); 1204 return (NULL); 1205 } 1206 1207 if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) { 1208 const Elf32_Sym *symp = (Elf32_Sym *)symbase + idx; 1209 if (ELF32_ST_TYPE(symp->st_info) != STT_OBJECT && 1210 ELF32_ST_TYPE(symp->st_info) != STT_FUNC) { 1211 (void) ctf_set_errno(fp, ECTF_NOTDATA); 1212 return (NULL); 1213 } 1214 if (symp->st_name == 0) { 1215 (void) ctf_set_errno(fp, ENOENT); 1216 return (NULL); 1217 } 1218 name = (const char *)(strbase + symp->st_name); 1219 } else { 1220 const Elf64_Sym *symp = (Elf64_Sym *)symbase + idx; 1221 if (ELF64_ST_TYPE(symp->st_info) != STT_FUNC && 1222 ELF64_ST_TYPE(symp->st_info) != STT_OBJECT) { 1223 (void) ctf_set_errno(fp, ECTF_NOTDATA); 1224 return (NULL); 1225 } 1226 if (symp->st_name == 0) { 1227 (void) ctf_set_errno(fp, ENOENT); 1228 return (NULL); 1229 } 1230 name = (const char *)(strbase + symp->st_name); 1231 } 1232 1233 (void) strlcpy(buf, name, len); 1234 1235 return (buf); 1236 } 1237 1238 int 1239 ctf_string_iter(ctf_file_t *fp, ctf_string_f *func, void *arg) 1240 { 1241 int rc; 1242 const char *strp = fp->ctf_str[CTF_STRTAB_0].cts_strs; 1243 size_t strl = fp->ctf_str[CTF_STRTAB_0].cts_len; 1244 1245 while (strl > 0) { 1246 size_t len; 1247 1248 if ((rc = func(strp, arg)) != 0) 1249 return (rc); 1250 1251 len = strlen(strp) + 1; 1252 strl -= len; 1253 strp += len; 1254 } 1255 1256 return (0); 1257 } 1258 1259 /* 1260 * fp isn't strictly necessary at the moment. However, if we ever rev the file 1261 * format, the valid values for kind will change. 1262 */ 1263 const char * 1264 ctf_kind_name(ctf_file_t *fp, int kind) 1265 { 1266 switch (kind) { 1267 case CTF_K_INTEGER: 1268 return ("integer"); 1269 case CTF_K_FLOAT: 1270 return ("float"); 1271 case CTF_K_POINTER: 1272 return ("pointer"); 1273 case CTF_K_ARRAY: 1274 return ("array"); 1275 case CTF_K_FUNCTION: 1276 return ("function"); 1277 case CTF_K_STRUCT: 1278 return ("struct"); 1279 case CTF_K_UNION: 1280 return ("union"); 1281 case CTF_K_ENUM: 1282 return ("enum"); 1283 case CTF_K_FORWARD: 1284 return ("forward"); 1285 case CTF_K_TYPEDEF: 1286 return ("typedef"); 1287 case CTF_K_VOLATILE: 1288 return ("volatile"); 1289 case CTF_K_CONST: 1290 return ("const"); 1291 case CTF_K_RESTRICT: 1292 return ("restrict"); 1293 case CTF_K_UNKNOWN: 1294 default: 1295 return ("unknown"); 1296 } 1297 } 1298 1299 ctf_id_t 1300 ctf_max_id(ctf_file_t *fp) 1301 { 1302 int child = (fp->ctf_flags & LCTF_CHILD); 1303 return (fp->ctf_typemax + (child ? CTF_CHILD_START : 0)); 1304 } 1305 1306 ulong_t 1307 ctf_nr_syms(ctf_file_t *fp) 1308 { 1309 return (fp->ctf_nsyms); 1310 } 1311