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