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
34ssize_t
35ctf_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
57void
58ctf_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 */
73int
74ctf_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 */
124int
125ctf_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 */
161int
162ctf_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 */
185ctf_id_t
186ctf_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 */
219static const char *
220ctf_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
243static void
244ctf_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
283out:
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 */
295static ssize_t
296ctf_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
435ssize_t
436ctf_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 */
445char *
446ctf_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
452char *
453ctf_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
460char *
461ctf_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 */
472ssize_t
473ctf_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 */
539ssize_t
540ctf_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 */
601int
602ctf_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 */
616ctf_id_t
617ctf_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 */
644ctf_id_t
645ctf_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 */
671int
672ctf_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
704int
705ctf_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 */
740int
741ctf_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 */
794int
795ctf_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 */
845int
846ctf_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 */
873const char *
874ctf_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 */
910int
911ctf_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 */
953static int
954ctf_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 */
1010int
1011ctf_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
1016int
1017ctf_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
1050int
1051ctf_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
1079int
1080ctf_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
1128int
1129ctf_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
1195char *
1196ctf_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
1248int
1249ctf_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 */
1273const char *
1274ctf_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
1309ctf_id_t
1310ctf_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
1316ulong_t
1317ctf_nr_syms(ctf_file_t *fp)
1318{
1319	return (fp->ctf_nsyms);
1320}
1321