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