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