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