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 }