xref: /freebsd/cddl/contrib/opensolaris/common/ctf/ctf_types.c (revision 6e563a1b608438504d963c2d7c70e50d2e75af46)
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 #include <ctf_impl.h>
29 
30 void
ctf_get_ctt_index(const ctf_file_t * fp,const void * v,uint_t * indexp,uint_t * typep,int * ischildp)31 ctf_get_ctt_index(const ctf_file_t *fp, const void *v, uint_t *indexp,
32     uint_t *typep, int *ischildp)
33 {
34 	uint_t index, type;
35 	int ischild;
36 
37 	if (fp->ctf_version == CTF_VERSION_2) {
38 		const struct ctf_type_v2 *ctt = v;
39 
40 		type = ctt->ctt_type;
41 		index = CTF_V2_TYPE_TO_INDEX(ctt->ctt_type);
42 		ischild = CTF_V2_TYPE_ISCHILD(ctt->ctt_type);
43 	} else {
44 		const struct ctf_type_v3 *ctt = v;
45 
46 		type = ctt->ctt_type;
47 		index = CTF_V3_TYPE_TO_INDEX(ctt->ctt_type);
48 		ischild = CTF_V3_TYPE_ISCHILD(ctt->ctt_type);
49 	}
50 
51 	if (indexp != NULL)
52 		*indexp = index;
53 	if (typep != NULL)
54 		*typep = type;
55 	if (ischildp != NULL)
56 		*ischildp = ischild;
57 }
58 
59 void
ctf_get_ctt_info(const ctf_file_t * fp,const void * v,uint_t * kindp,uint_t * vlenp,int * isrootp)60 ctf_get_ctt_info(const ctf_file_t *fp, const void *v, uint_t *kindp,
61     uint_t *vlenp, int *isrootp)
62 {
63 	uint_t kind, vlen;
64 	int isroot;
65 
66 	if (fp->ctf_version == CTF_VERSION_2) {
67 		const struct ctf_type_v2 *ctt = v;
68 
69 		kind = CTF_V2_INFO_KIND(ctt->ctt_info);
70 		vlen = CTF_V2_INFO_VLEN(ctt->ctt_info);
71 		isroot = CTF_V2_INFO_ISROOT(ctt->ctt_info);
72 	} else {
73 		const struct ctf_type_v3 *ctt = v;
74 
75 		kind = CTF_V3_INFO_KIND(ctt->ctt_info);
76 		vlen = CTF_V3_INFO_VLEN(ctt->ctt_info);
77 		isroot = CTF_V3_INFO_ISROOT(ctt->ctt_info);
78 	}
79 
80 	if (kindp != NULL)
81 		*kindp = kind;
82 	if (vlenp != NULL)
83 		*vlenp = vlen;
84 	if (isrootp != NULL)
85 		*isrootp = isroot;
86 }
87 
88 ssize_t
ctf_get_ctt_size(const ctf_file_t * fp,const void * v,ssize_t * sizep,ssize_t * incrementp)89 ctf_get_ctt_size(const ctf_file_t *fp, const void *v, ssize_t *sizep,
90     ssize_t *incrementp)
91 {
92 	ssize_t size, increment;
93 
94 	if (fp->ctf_version == CTF_VERSION_2) {
95 		const struct ctf_type_v2 *ctt = v;
96 
97 		if (ctt->ctt_size == CTF_V2_LSIZE_SENT) {
98 			size = (size_t)CTF_TYPE_LSIZE(ctt);
99 			increment = sizeof (struct ctf_type_v2);
100 		} else {
101 			size = ctt->ctt_size;
102 			increment = sizeof (struct ctf_stype_v2);
103 		}
104 	} else {
105 		const struct ctf_type_v3 *ctt = v;
106 
107 		if (ctt->ctt_size == CTF_V3_LSIZE_SENT) {
108 			size = (size_t)CTF_TYPE_LSIZE(ctt);
109 			increment = sizeof (struct ctf_type_v3);
110 		} else {
111 			size = ctt->ctt_size;
112 			increment = sizeof (struct ctf_stype_v3);
113 		}
114 	}
115 
116 	if (sizep)
117 		*sizep = size;
118 	if (incrementp)
119 		*incrementp = increment;
120 
121 	return (size);
122 }
123 
124 /*
125  * Fetch info for a struct or union member.
126  */
127 void
ctf_get_ctm_info(const ctf_file_t * fp,const void * v,size_t size,size_t * incrementp,uint_t * typep,ulong_t * offsetp,const char ** namep)128 ctf_get_ctm_info(const ctf_file_t *fp, const void *v, size_t size,
129     size_t *incrementp, uint_t *typep, ulong_t *offsetp, const char **namep)
130 {
131 	size_t increment;
132 	ulong_t offset;
133 	uint_t name, type;
134 
135 	if (fp->ctf_version == CTF_VERSION_2) {
136 		if (size < CTF_V2_LSTRUCT_THRESH) {
137 			const struct ctf_member_v2 *ctm = v;
138 
139 			name = ctm->ctm_name;
140 			type = ctm->ctm_type;
141 			offset = ctm->ctm_offset;
142 			increment = sizeof(*ctm);
143 		} else {
144 			const struct ctf_lmember_v2 *ctlm = v;
145 
146 			name = ctlm->ctlm_name;
147 			type = ctlm->ctlm_type;
148 			offset = (ulong_t)CTF_LMEM_OFFSET(ctlm);
149 			increment = sizeof(*ctlm);
150 		}
151 	} else {
152 		if (size < CTF_V3_LSTRUCT_THRESH) {
153 			const struct ctf_member_v3 *ctm = v;
154 
155 			name = ctm->ctm_name;
156 			type = ctm->ctm_type;
157 			offset = ctm->ctm_offset;
158 			increment = sizeof(*ctm);
159 		} else {
160 			const struct ctf_lmember_v3 *ctlm = v;
161 
162 			name = ctlm->ctlm_name;
163 			type = ctlm->ctlm_type;
164 			offset = (ulong_t)CTF_LMEM_OFFSET(ctlm);
165 			increment = sizeof(*ctlm);
166 		}
167 	}
168 
169 	if (incrementp != NULL)
170 		*incrementp = increment;
171 	if (typep != NULL)
172 		*typep = type;
173 	if (offsetp != NULL)
174 		*offsetp = offset;
175 	if (namep != NULL)
176 		*namep = ctf_strraw(fp, name);
177 }
178 
179 /*
180  * Iterate over the members of a STRUCT or UNION.  We pass the name, member
181  * type, and offset of each member to the specified callback function.
182  */
183 int
ctf_member_iter(ctf_file_t * fp,ctf_id_t type,ctf_member_f * func,void * arg)184 ctf_member_iter(ctf_file_t *fp, ctf_id_t type, ctf_member_f *func, void *arg)
185 {
186 	ctf_file_t *ofp = fp;
187 	const void *tp;
188 	ssize_t size, increment;
189 	uint_t kind, n, vlen;
190 	int rc;
191 
192 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
193 		return (CTF_ERR); /* errno is set for us */
194 
195 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
196 		return (CTF_ERR); /* errno is set for us */
197 
198 	(void) ctf_get_ctt_size(fp, tp, &size, &increment);
199 	ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
200 
201 	if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
202 		return (ctf_set_errno(ofp, ECTF_NOTSOU));
203 
204 	const char *mp = (const char *)((uintptr_t)tp + increment);
205 
206 	for (n = vlen; n != 0; n--, mp += increment) {
207 		const char *name;
208 		ulong_t offset;
209 		uint_t type;
210 
211 		ctf_get_ctm_info(fp, mp, size, &increment, &type, &offset,
212 		    &name);
213 		if ((rc = func(name, type, offset, arg)) != 0)
214 			return (rc);
215 	}
216 
217 	return (0);
218 }
219 
220 /*
221  * Iterate over the members of an ENUM.  We pass the string name and associated
222  * integer value of each enum element to the specified callback function.
223  */
224 int
ctf_enum_iter(ctf_file_t * fp,ctf_id_t type,ctf_enum_f * func,void * arg)225 ctf_enum_iter(ctf_file_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg)
226 {
227 	ctf_file_t *ofp = fp;
228 	const void *tp;
229 	const ctf_enum_t *ep;
230 	ssize_t increment;
231 	uint_t kind, n, vlen;
232 	int rc;
233 
234 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
235 		return (CTF_ERR); /* errno is set for us */
236 
237 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
238 		return (CTF_ERR); /* errno is set for us */
239 
240 	ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
241 	if (kind != CTF_K_ENUM)
242 		return (ctf_set_errno(ofp, ECTF_NOTENUM));
243 
244 	(void) ctf_get_ctt_size(fp, tp, NULL, &increment);
245 
246 	ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
247 
248 	for (n = vlen; n != 0; n--, ep++) {
249 		const char *name = ctf_strptr(fp, ep->cte_name);
250 		if ((rc = func(name, ep->cte_value, arg)) != 0)
251 			return (rc);
252 	}
253 
254 	return (0);
255 }
256 
257 /*
258  * Iterate over every root (user-visible) type in the given CTF container.
259  * We pass the type ID of each type to the specified callback function.
260  */
261 int
ctf_type_iter(ctf_file_t * fp,ctf_type_f * func,void * arg)262 ctf_type_iter(ctf_file_t *fp, ctf_type_f *func, void *arg)
263 {
264 	ctf_id_t id, max = fp->ctf_typemax;
265 	int rc, child = (fp->ctf_flags & LCTF_CHILD);
266 	int isroot;
267 
268 	for (id = 1; id <= max; id++) {
269 		const void *tp = LCTF_INDEX_TO_TYPEPTR(fp, id);
270 		ctf_get_ctt_info(fp, tp, NULL, NULL, &isroot);
271 		if (isroot &&
272 		    (rc = func(LCTF_INDEX_TO_TYPE(fp, id, child), arg)) != 0)
273 			return (rc);
274 	}
275 
276 	return (0);
277 }
278 
279 /*
280  * Follow a given type through the graph for TYPEDEF, VOLATILE, CONST, and
281  * RESTRICT nodes until we reach a "base" type node.  This is useful when
282  * we want to follow a type ID to a node that has members or a size.  To guard
283  * against infinite loops, we implement simplified cycle detection and check
284  * each link against itself, the previous node, and the topmost node.
285  */
286 ctf_id_t
ctf_type_resolve(ctf_file_t * fp,ctf_id_t type)287 ctf_type_resolve(ctf_file_t *fp, ctf_id_t type)
288 {
289 	ctf_id_t prev = type, otype = type;
290 	ctf_file_t *ofp = fp;
291 	const void *tp;
292 	uint_t kind, ctype;
293 
294 	while ((tp = ctf_lookup_by_id(&fp, type)) != NULL) {
295 		ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
296 		switch (kind) {
297 		case CTF_K_TYPEDEF:
298 		case CTF_K_VOLATILE:
299 		case CTF_K_CONST:
300 		case CTF_K_RESTRICT:
301 			ctf_get_ctt_index(fp, tp, NULL, &ctype, NULL);
302 			if (ctype == type || ctype == otype || ctype == prev) {
303 				ctf_dprintf("type %ld cycle detected\n", otype);
304 				return (ctf_set_errno(ofp, ECTF_CORRUPT));
305 			}
306 			prev = type;
307 			type = ctype;
308 			break;
309 		default:
310 			return (type);
311 		}
312 	}
313 
314 	return (CTF_ERR); /* errno is set for us */
315 }
316 
317 /*
318  * Lookup the given type ID and print a string name for it into buf.  Return
319  * the actual number of bytes (not including \0) needed to format the name.
320  */
321 static ssize_t
ctf_type_qlname(ctf_file_t * fp,ctf_id_t type,char * buf,size_t len,const char * qname)322 ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
323     const char *qname)
324 {
325 	ctf_decl_t cd;
326 	ctf_decl_node_t *cdp;
327 	ctf_decl_prec_t prec, lp, rp;
328 	int ptr, arr;
329 	uint_t k;
330 
331 	if (fp == NULL && type == CTF_ERR)
332 		return (-1); /* simplify caller code by permitting CTF_ERR */
333 
334 	ctf_decl_init(&cd, buf, len);
335 	ctf_decl_push(&cd, fp, type);
336 
337 	if (cd.cd_err != 0) {
338 		ctf_decl_fini(&cd);
339 		return (ctf_set_errno(fp, cd.cd_err));
340 	}
341 
342 	/*
343 	 * If the type graph's order conflicts with lexical precedence order
344 	 * for pointers or arrays, then we need to surround the declarations at
345 	 * the corresponding lexical precedence with parentheses.  This can
346 	 * result in either a parenthesized pointer (*) as in int (*)() or
347 	 * int (*)[], or in a parenthesized pointer and array as in int (*[])().
348 	 */
349 	ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER;
350 	arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY;
351 
352 	rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1;
353 	lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1;
354 
355 	k = CTF_K_POINTER; /* avoid leading whitespace (see below) */
356 
357 	for (prec = CTF_PREC_BASE; prec < CTF_PREC_MAX; prec++) {
358 		for (cdp = ctf_list_next(&cd.cd_nodes[prec]);
359 		    cdp != NULL; cdp = ctf_list_next(cdp)) {
360 
361 			ctf_file_t *rfp = fp;
362 			const void *tp = ctf_lookup_by_id(&rfp, cdp->cd_type);
363 			const char *name = ctf_type_rname(rfp, tp);
364 
365 			if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
366 				ctf_decl_sprintf(&cd, " ");
367 
368 			if (lp == prec) {
369 				ctf_decl_sprintf(&cd, "(");
370 				lp = -1;
371 			}
372 
373 			switch (cdp->cd_kind) {
374 			case CTF_K_INTEGER:
375 			case CTF_K_FLOAT:
376 			case CTF_K_TYPEDEF:
377 				if (qname != NULL)
378 					ctf_decl_sprintf(&cd, "%s`", qname);
379 				ctf_decl_sprintf(&cd, "%s", name);
380 				break;
381 			case CTF_K_POINTER:
382 				ctf_decl_sprintf(&cd, "*");
383 				break;
384 			case CTF_K_ARRAY:
385 				ctf_decl_sprintf(&cd, "[%u]", cdp->cd_n);
386 				break;
387 			case CTF_K_FUNCTION:
388 				ctf_decl_sprintf(&cd, "()");
389 				break;
390 			case CTF_K_STRUCT:
391 			case CTF_K_FORWARD:
392 				ctf_decl_sprintf(&cd, "struct ");
393 				if (qname != NULL)
394 					ctf_decl_sprintf(&cd, "%s`", qname);
395 				ctf_decl_sprintf(&cd, "%s", name);
396 				break;
397 			case CTF_K_UNION:
398 				ctf_decl_sprintf(&cd, "union ");
399 				if (qname != NULL)
400 					ctf_decl_sprintf(&cd, "%s`", qname);
401 				ctf_decl_sprintf(&cd, "%s", name);
402 				break;
403 			case CTF_K_ENUM:
404 				ctf_decl_sprintf(&cd, "enum ");
405 				if (qname != NULL)
406 					ctf_decl_sprintf(&cd, "%s`", qname);
407 				ctf_decl_sprintf(&cd, "%s", name);
408 				break;
409 			case CTF_K_VOLATILE:
410 				ctf_decl_sprintf(&cd, "volatile");
411 				break;
412 			case CTF_K_CONST:
413 				ctf_decl_sprintf(&cd, "const");
414 				break;
415 			case CTF_K_RESTRICT:
416 				ctf_decl_sprintf(&cd, "restrict");
417 				break;
418 			}
419 
420 			k = cdp->cd_kind;
421 		}
422 
423 		if (rp == prec)
424 			ctf_decl_sprintf(&cd, ")");
425 	}
426 
427 	if (cd.cd_len >= len)
428 		(void) ctf_set_errno(fp, ECTF_NAMELEN);
429 
430 	ctf_decl_fini(&cd);
431 	return (cd.cd_len);
432 }
433 
434 ssize_t
ctf_type_lname(ctf_file_t * fp,ctf_id_t type,char * buf,size_t len)435 ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
436 {
437 	return (ctf_type_qlname(fp, type, buf, len, NULL));
438 }
439 
440 /*
441  * Lookup the given type ID and print a string name for it into buf.  If buf
442  * is too small, return NULL: the ECTF_NAMELEN error is set on 'fp' for us.
443  */
444 char *
ctf_type_name(ctf_file_t * fp,ctf_id_t type,char * buf,size_t len)445 ctf_type_name(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
446 {
447 	ssize_t rv = ctf_type_qlname(fp, type, buf, len, NULL);
448 	return (rv >= 0 && rv < len ? buf : NULL);
449 }
450 
451 char *
ctf_type_qname(ctf_file_t * fp,ctf_id_t type,char * buf,size_t len,const char * qname)452 ctf_type_qname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
453     const char *qname)
454 {
455 	ssize_t rv = ctf_type_qlname(fp, type, buf, len, qname);
456 	return (rv >= 0 && rv < len ? buf : NULL);
457 }
458 
459 const char *
ctf_type_rname(ctf_file_t * fp,const void * v)460 ctf_type_rname(ctf_file_t *fp, const void *v)
461 {
462 	uint_t name;
463 
464 	if (fp->ctf_version == CTF_VERSION_2) {
465 		const struct ctf_type_v2 *ctt = v;
466 
467 		name = ctt->ctt_name;
468 	} else {
469 		const struct ctf_type_v3 *ctt = v;
470 
471 		name = ctt->ctt_name;
472 	}
473 
474 	return (ctf_strptr(fp, name));
475 }
476 
477 /*
478  * Resolve the type down to a base type node, and then return the size
479  * of the type storage in bytes.
480  */
481 ssize_t
ctf_type_size(ctf_file_t * fp,ctf_id_t type)482 ctf_type_size(ctf_file_t *fp, ctf_id_t type)
483 {
484 	const void *tp;
485 	ssize_t size;
486 	ctf_arinfo_t ar;
487 	uint_t kind;
488 
489 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
490 		return (-1); /* errno is set for us */
491 
492 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
493 		return (-1); /* errno is set for us */
494 
495 	ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
496 
497 	switch (kind) {
498 	case CTF_K_POINTER:
499 		return (fp->ctf_dmodel->ctd_pointer);
500 
501 	case CTF_K_FUNCTION:
502 		return (0); /* function size is only known by symtab */
503 
504 	case CTF_K_ENUM:
505 		return (fp->ctf_dmodel->ctd_int);
506 
507 	case CTF_K_ARRAY:
508 		/*
509 		 * Array size is not directly returned by stabs data.  Instead,
510 		 * it defines the element type and requires the user to perform
511 		 * the multiplication.  If ctf_get_ctt_size() returns zero, the
512 		 * current version of ctfconvert does not compute member sizes
513 		 * and we compute the size here on its behalf.
514 		 */
515 		if ((size = ctf_get_ctt_size(fp, tp, NULL, NULL)) > 0)
516 			return (size);
517 
518 		if (ctf_array_info(fp, type, &ar) == CTF_ERR ||
519 		    (size = ctf_type_size(fp, ar.ctr_contents)) == CTF_ERR)
520 			return (-1); /* errno is set for us */
521 
522 		return (size * ar.ctr_nelems);
523 
524 	default:
525 		return (ctf_get_ctt_size(fp, tp, NULL, NULL));
526 	}
527 }
528 
529 /*
530  * Resolve the type down to a base type node, and then return the alignment
531  * needed for the type storage in bytes.
532  */
533 ssize_t
ctf_type_align(ctf_file_t * fp,ctf_id_t type)534 ctf_type_align(ctf_file_t *fp, ctf_id_t type)
535 {
536 	const void *tp;
537 	ctf_arinfo_t r;
538 	uint_t kind, vlen;
539 
540 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
541 		return (-1); /* errno is set for us */
542 
543 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
544 		return (-1); /* errno is set for us */
545 
546 	ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
547 
548 	switch (kind) {
549 	case CTF_K_POINTER:
550 	case CTF_K_FUNCTION:
551 		return (fp->ctf_dmodel->ctd_pointer);
552 
553 	case CTF_K_ARRAY:
554 		if (ctf_array_info(fp, type, &r) == CTF_ERR)
555 			return (-1); /* errno is set for us */
556 		return (ctf_type_align(fp, r.ctr_contents));
557 
558 	case CTF_K_STRUCT:
559 	case CTF_K_UNION: {
560 		uint_t n = vlen;
561 		ssize_t size, increment;
562 		size_t align = 0;
563 		const void *vmp;
564 
565 		(void) ctf_get_ctt_size(fp, tp, &size, &increment);
566 		vmp = (uchar_t *)tp + increment;
567 
568 		if (kind == CTF_K_STRUCT)
569 			n = MIN(n, 1); /* only use first member for structs */
570 
571 		for (const char *mp = vmp; n != 0; n--, mp += increment) {
572 			uint_t type;
573 
574 			ctf_get_ctm_info(fp, mp, size, &increment, &type,
575 			    NULL, NULL);
576 			ssize_t am = ctf_type_align(fp, type);
577 			align = MAX(align, am);
578 		}
579 
580 		return (align);
581 	}
582 
583 	case CTF_K_ENUM:
584 		return (fp->ctf_dmodel->ctd_int);
585 
586 	default:
587 		return (ctf_get_ctt_size(fp, tp, NULL, NULL));
588 	}
589 }
590 
591 /*
592  * Return the kind (CTF_K_* constant) for the specified type ID.
593  */
594 int
ctf_type_kind(ctf_file_t * fp,ctf_id_t type)595 ctf_type_kind(ctf_file_t *fp, ctf_id_t type)
596 {
597 	const void *tp;
598 	uint_t kind;
599 
600 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
601 		return (CTF_ERR); /* errno is set for us */
602 
603 	ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
604 
605 	return (kind);
606 }
607 
608 /*
609  * If the type is one that directly references another type (such as POINTER),
610  * then return the ID of the type to which it refers.
611  */
612 ctf_id_t
ctf_type_reference(ctf_file_t * fp,ctf_id_t type)613 ctf_type_reference(ctf_file_t *fp, ctf_id_t type)
614 {
615 	ctf_file_t *ofp = fp;
616 	const void *tp;
617 	uint_t ctype, kind;
618 
619 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
620 		return (CTF_ERR); /* errno is set for us */
621 
622 	ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
623 
624 	switch (kind) {
625 	case CTF_K_POINTER:
626 	case CTF_K_TYPEDEF:
627 	case CTF_K_VOLATILE:
628 	case CTF_K_CONST:
629 	case CTF_K_RESTRICT:
630 		ctf_get_ctt_index(fp, tp, NULL, &ctype, NULL);
631 		return (ctype);
632 	default:
633 		return (ctf_set_errno(ofp, ECTF_NOTREF));
634 	}
635 }
636 
637 /*
638  * Find a pointer to type by looking in fp->ctf_ptrtab.  If we can't find a
639  * pointer to the given type, see if we can compute a pointer to the type
640  * resulting from resolving the type down to its base type and use that
641  * instead.  This helps with cases where the CTF data includes "struct foo *"
642  * but not "foo_t *" and the user accesses "foo_t *" in the debugger.
643  */
644 ctf_id_t
ctf_type_pointer(ctf_file_t * fp,ctf_id_t type)645 ctf_type_pointer(ctf_file_t *fp, ctf_id_t type)
646 {
647 	ctf_file_t *ofp = fp;
648 	ctf_id_t ntype;
649 
650 	if (ctf_lookup_by_id(&fp, type) == NULL)
651 		return (CTF_ERR); /* errno is set for us */
652 
653 	if ((ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX(fp, type)]) != 0)
654 		return (LCTF_INDEX_TO_TYPE(fp, 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[LCTF_TYPE_TO_INDEX(fp, type)]) != 0)
663 		return (LCTF_INDEX_TO_TYPE(fp, ntype, (fp->ctf_flags & LCTF_CHILD)));
664 
665 	return (ctf_set_errno(ofp, ECTF_NOTYPE));
666 }
667 
668 /*
669  * Return the encoding for the specified INTEGER or FLOAT.
670  */
671 int
ctf_type_encoding(ctf_file_t * fp,ctf_id_t type,ctf_encoding_t * ep)672 ctf_type_encoding(ctf_file_t *fp, ctf_id_t type, ctf_encoding_t *ep)
673 {
674 	ctf_file_t *ofp = fp;
675 	const void *tp;
676 	ssize_t increment;
677 	uint_t data, kind;
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 	ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
684 
685 	switch (kind) {
686 	case CTF_K_INTEGER:
687 		data = *(const uint_t *)((uintptr_t)tp + increment);
688 		ep->cte_format = CTF_INT_ENCODING(data);
689 		ep->cte_offset = CTF_INT_OFFSET(data);
690 		ep->cte_bits = CTF_INT_BITS(data);
691 		break;
692 	case CTF_K_FLOAT:
693 		data = *(const uint_t *)((uintptr_t)tp + increment);
694 		ep->cte_format = CTF_FP_ENCODING(data);
695 		ep->cte_offset = CTF_FP_OFFSET(data);
696 		ep->cte_bits = CTF_FP_BITS(data);
697 		break;
698 	default:
699 		return (ctf_set_errno(ofp, ECTF_NOTINTFP));
700 	}
701 
702 	return (0);
703 }
704 
705 int
ctf_type_cmp(ctf_file_t * lfp,ctf_id_t ltype,ctf_file_t * rfp,ctf_id_t rtype)706 ctf_type_cmp(ctf_file_t *lfp, ctf_id_t ltype, ctf_file_t *rfp, ctf_id_t rtype)
707 {
708 	int rval;
709 
710 	if (ltype < rtype)
711 		rval = -1;
712 	else if (ltype > rtype)
713 		rval = 1;
714 	else
715 		rval = 0;
716 
717 	if (lfp == rfp)
718 		return (rval);
719 
720 	if (LCTF_TYPE_ISPARENT(lfp, ltype) && lfp->ctf_parent != NULL)
721 		lfp = lfp->ctf_parent;
722 
723 	if (LCTF_TYPE_ISPARENT(rfp, rtype) && rfp->ctf_parent != NULL)
724 		rfp = rfp->ctf_parent;
725 
726 	if (lfp < rfp)
727 		return (-1);
728 
729 	if (lfp > rfp)
730 		return (1);
731 
732 	return (rval);
733 }
734 
735 /*
736  * Return a boolean value indicating if two types are compatible integers or
737  * floating-pointer values.  This function returns true if the two types are
738  * the same, or if they have the same ASCII name and encoding properties.
739  * This function could be extended to test for compatibility for other kinds.
740  */
741 int
ctf_type_compat(ctf_file_t * lfp,ctf_id_t ltype,ctf_file_t * rfp,ctf_id_t rtype)742 ctf_type_compat(ctf_file_t *lfp, ctf_id_t ltype,
743     ctf_file_t *rfp, ctf_id_t rtype)
744 {
745 	const void *ltp, *rtp;
746 	ctf_encoding_t le, re;
747 	ctf_arinfo_t la, ra;
748 	uint_t lkind, rkind;
749 
750 	if (ctf_type_cmp(lfp, ltype, rfp, rtype) == 0)
751 		return (1);
752 
753 	ltype = ctf_type_resolve(lfp, ltype);
754 	lkind = ctf_type_kind(lfp, ltype);
755 
756 	rtype = ctf_type_resolve(rfp, rtype);
757 	rkind = ctf_type_kind(rfp, rtype);
758 
759 	if (lkind != rkind ||
760 	    (ltp = ctf_lookup_by_id(&lfp, ltype)) == NULL ||
761 	    (rtp = ctf_lookup_by_id(&rfp, rtype)) == NULL ||
762 	    strcmp(ctf_type_rname(lfp, ltp), ctf_type_rname(rfp, rtp)) != 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 static int
_ctf_member_info(ctf_file_t * fp,ctf_id_t type,const char * name,ulong_t off,ctf_membinfo_t * mip)792 _ctf_member_info(ctf_file_t *fp, ctf_id_t type, const char *name, ulong_t off,
793     ctf_membinfo_t *mip)
794 {
795 	ctf_file_t *ofp = fp;
796 	const void *tp;
797 	ssize_t size, increment;
798 	uint_t kind, n, vlen;
799 
800 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
801 		return (CTF_ERR); /* errno is set for us */
802 
803 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
804 		return (CTF_ERR); /* errno is set for us */
805 
806 	(void) ctf_get_ctt_size(fp, tp, &size, &increment);
807 	ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
808 
809 	if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
810 		return (ctf_set_errno(ofp, ECTF_NOTSOU));
811 
812 	const char *mp = (const char *)((uintptr_t)tp + increment);
813 
814 	for (n = vlen; n != 0; n--, mp += increment) {
815 		const char *name1;
816 		ulong_t offset;
817 		uint_t type;
818 
819 		ctf_get_ctm_info(fp, mp, size, &increment, &type, &offset,
820 		    &name1);
821 		if (name1[0] == '\0' &&
822 		    _ctf_member_info(fp, type, name, offset + off, mip) == 0)
823 			return (0);
824 		if (strcmp(name1, name) == 0) {
825 			mip->ctm_type = type;
826 			mip->ctm_offset = offset + off;
827 			return (0);
828 		}
829 	}
830 
831 	return (ctf_set_errno(ofp, ECTF_NOMEMBNAM));
832 }
833 
834 /*
835  * Return the type and offset for a given member of a STRUCT or UNION.
836  */
837 int
ctf_member_info(ctf_file_t * fp,ctf_id_t type,const char * name,ctf_membinfo_t * mip)838 ctf_member_info(ctf_file_t *fp, ctf_id_t type, const char *name,
839     ctf_membinfo_t *mip)
840 {
841 
842 	return (_ctf_member_info(fp, type, name, 0, mip));
843 }
844 
845 /*
846  * Return the array type, index, and size information for the specified ARRAY.
847  */
848 int
ctf_array_info(ctf_file_t * fp,ctf_id_t type,ctf_arinfo_t * arp)849 ctf_array_info(ctf_file_t *fp, ctf_id_t type, ctf_arinfo_t *arp)
850 {
851 	ctf_file_t *ofp = fp;
852 	const void *ap, *tp;
853 	ssize_t increment;
854 	uint_t kind;
855 
856 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
857 		return (CTF_ERR); /* errno is set for us */
858 
859 	ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
860 
861 	if (kind != CTF_K_ARRAY)
862 		return (ctf_set_errno(ofp, ECTF_NOTARRAY));
863 
864 	(void) ctf_get_ctt_size(fp, tp, NULL, &increment);
865 
866 	ap = (const void *)((uintptr_t)tp + increment);
867 	if (fp->ctf_version == CTF_VERSION_2) {
868 		const struct ctf_array_v2 *ap2 = ap;
869 
870 		arp->ctr_contents = ap2->cta_contents;
871 		arp->ctr_index = ap2->cta_index;
872 		arp->ctr_nelems = ap2->cta_nelems;
873 	} else {
874 		const struct ctf_array_v3 *ap3 = ap;
875 
876 		arp->ctr_contents = ap3->cta_contents;
877 		arp->ctr_index = ap3->cta_index;
878 		arp->ctr_nelems = ap3->cta_nelems;
879 	}
880 
881 	return (0);
882 }
883 
884 /*
885  * Convert the specified value to the corresponding enum member name, if a
886  * matching name can be found.  Otherwise NULL is returned.
887  */
888 const char *
ctf_enum_name(ctf_file_t * fp,ctf_id_t type,int value)889 ctf_enum_name(ctf_file_t *fp, ctf_id_t type, int value)
890 {
891 	ctf_file_t *ofp = fp;
892 	const void *tp;
893 	const ctf_enum_t *ep;
894 	ssize_t increment;
895 	uint_t kind, n, vlen;
896 
897 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
898 		return (NULL); /* errno is set for us */
899 
900 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
901 		return (NULL); /* errno is set for us */
902 
903 	ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
904 
905 	if (kind != CTF_K_ENUM) {
906 		(void) ctf_set_errno(ofp, ECTF_NOTENUM);
907 		return (NULL);
908 	}
909 
910 	(void) ctf_get_ctt_size(fp, tp, NULL, &increment);
911 
912 	ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
913 
914 	for (n = vlen; n != 0; n--, ep++) {
915 		if (ep->cte_value == value)
916 			return (ctf_strptr(fp, ep->cte_name));
917 	}
918 
919 	(void) ctf_set_errno(ofp, ECTF_NOENUMNAM);
920 	return (NULL);
921 }
922 
923 /*
924  * Convert the specified enum tag name to the corresponding value, if a
925  * matching name can be found.  Otherwise CTF_ERR is returned.
926  */
927 int
ctf_enum_value(ctf_file_t * fp,ctf_id_t type,const char * name,int * valp)928 ctf_enum_value(ctf_file_t *fp, ctf_id_t type, const char *name, int *valp)
929 {
930 	ctf_file_t *ofp = fp;
931 	const void *tp;
932 	const ctf_enum_t *ep;
933 	ssize_t size, increment;
934 	uint_t kind, n, vlen;
935 
936 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
937 		return (CTF_ERR); /* errno is set for us */
938 
939 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
940 		return (CTF_ERR); /* errno is set for us */
941 
942 	ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
943 
944 	if (kind != CTF_K_ENUM) {
945 		(void) ctf_set_errno(ofp, ECTF_NOTENUM);
946 		return (CTF_ERR);
947 	}
948 
949 	(void) ctf_get_ctt_size(fp, tp, &size, &increment);
950 
951 	ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
952 
953 	for (n = vlen; n != 0; n--, ep++) {
954 		if (strcmp(ctf_strptr(fp, ep->cte_name), name) == 0) {
955 			if (valp != NULL)
956 				*valp = ep->cte_value;
957 			return (0);
958 		}
959 	}
960 
961 	(void) ctf_set_errno(ofp, ECTF_NOENUMNAM);
962 	return (CTF_ERR);
963 }
964 
965 /*
966  * Recursively visit the members of any type.  This function is used as the
967  * engine for ctf_type_visit, below.  We resolve the input type, recursively
968  * invoke ourself for each type member if the type is a struct or union, and
969  * then invoke the callback function on the current type.  If any callback
970  * returns non-zero, we abort and percolate the error code back up to the top.
971  */
972 static int
ctf_type_rvisit(ctf_file_t * fp,ctf_id_t type,ctf_visit_f * func,void * arg,const char * name,ulong_t offset,int depth)973 ctf_type_rvisit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg,
974     const char *name, ulong_t offset, int depth)
975 {
976 	ctf_id_t otype = type;
977 	const void *tp;
978 	ssize_t size, increment;
979 	uint_t kind, n, vlen;
980 	int rc;
981 
982 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
983 		return (CTF_ERR); /* errno is set for us */
984 
985 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
986 		return (CTF_ERR); /* errno is set for us */
987 
988 	if ((rc = func(name, otype, offset, depth, arg)) != 0)
989 		return (rc);
990 
991 	ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
992 
993 	if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
994 		return (0);
995 
996 	(void) ctf_get_ctt_size(fp, tp, &size, &increment);
997 
998 	const char *mp = (const char *)((uintptr_t)tp + increment);
999 	for (n = vlen; n != 0; n--, mp += increment) {
1000 		const char *name;
1001 		ulong_t offset1;
1002 		uint_t type;
1003 
1004 		ctf_get_ctm_info(fp, mp, size, &increment, &type, &offset1,
1005 		    &name);
1006 		if ((rc = ctf_type_rvisit(fp, type, func, arg, name,
1007 		    offset + offset1, depth + 1)) != 0)
1008 			return (rc);
1009 	}
1010 
1011 	return (0);
1012 }
1013 
1014 /*
1015  * Recursively visit the members of any type.  We pass the name, member
1016  * type, and offset of each member to the specified callback function.
1017  */
1018 int
ctf_type_visit(ctf_file_t * fp,ctf_id_t type,ctf_visit_f * func,void * arg)1019 ctf_type_visit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg)
1020 {
1021 	return (ctf_type_rvisit(fp, type, func, arg, "", 0, 0));
1022 }
1023