xref: /titanic_51/usr/src/lib/libtnf/abi.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  *	Copyright (c) 1994, by Sun Microsytems, Inc.
24*7c478bd9Sstevel@tonic-gate  */
25*7c478bd9Sstevel@tonic-gate 
26*7c478bd9Sstevel@tonic-gate #pragma	ident	"%Z%%M%	%I%	%E% SMI"
27*7c478bd9Sstevel@tonic-gate 
28*7c478bd9Sstevel@tonic-gate #include "libtnf.h"
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate /*
31*7c478bd9Sstevel@tonic-gate  * Operations based on ABI bootstrap assumptions
32*7c478bd9Sstevel@tonic-gate  */
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #define	_GET_TAG(tnf, p)		\
35*7c478bd9Sstevel@tonic-gate 	_GET_REF32(tnf, p)
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate #define	_GET_TAG_ARG(tnf, p)		\
38*7c478bd9Sstevel@tonic-gate 	_GET_REF16(tnf, p)
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate #define	_GET_SELF_SIZE(tnf, p) 		\
41*7c478bd9Sstevel@tonic-gate 	_GET_UINT32(tnf, &((struct tnf_array_hdr *)(p))->self_size)
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate #define	_GET_NAME(tnf, p)		\
44*7c478bd9Sstevel@tonic-gate 	_GET_REF32(tnf, &((struct tnf_type_hdr *)(p))->name)
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate #define	_GET_PROPERTIES(tnf, p)		\
47*7c478bd9Sstevel@tonic-gate 	_GET_REF32(tnf, &((struct tnf_type_hdr *)(p))->properties)
48*7c478bd9Sstevel@tonic-gate 
49*7c478bd9Sstevel@tonic-gate #define	_GET_SLOT_TYPES(tnf, p)		\
50*7c478bd9Sstevel@tonic-gate 	_GET_REF32(tnf, &((struct tnf_struct_type_hdr *)(p))->slot_types)
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate #define	_GET_TYPE_SIZE(tnf, p)		\
53*7c478bd9Sstevel@tonic-gate 	_GET_UINT32(tnf, &((struct tnf_struct_type_hdr *)(p))->type_size)
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate #define	_GET_HEADER_SIZE(tnf, p)	\
56*7c478bd9Sstevel@tonic-gate 	_GET_UINT32(tnf, &((struct tnf_array_type_hdr *)(p))->header_size)
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate #define	_GET_DERIVED_BASE(tnf, p)	\
59*7c478bd9Sstevel@tonic-gate 	_GET_REF32(tnf, &((struct tnf_derived_type_hdr *)(p))->derived_base)
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate /*
62*7c478bd9Sstevel@tonic-gate  * Static declarations
63*7c478bd9Sstevel@tonic-gate  */
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate static caddr_t	fetch_slot(TNF *, caddr_t, tnf_ref32_t *);
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate /*
68*7c478bd9Sstevel@tonic-gate  * retrieve tag slot from a record
69*7c478bd9Sstevel@tonic-gate  */
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate tnf_ref32_t *
72*7c478bd9Sstevel@tonic-gate _tnf_get_tag(TNF *tnf, tnf_ref32_t *record)
73*7c478bd9Sstevel@tonic-gate {
74*7c478bd9Sstevel@tonic-gate 	return (_GET_TAG(tnf, record));
75*7c478bd9Sstevel@tonic-gate }
76*7c478bd9Sstevel@tonic-gate 
77*7c478bd9Sstevel@tonic-gate /*
78*7c478bd9Sstevel@tonic-gate  * Retrieve tag_arg from tag slot of a record
79*7c478bd9Sstevel@tonic-gate  */
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate tnf_ref32_t *
82*7c478bd9Sstevel@tonic-gate _tnf_get_tag_arg(TNF *tnf, tnf_ref32_t *record)
83*7c478bd9Sstevel@tonic-gate {
84*7c478bd9Sstevel@tonic-gate 	return (_GET_TAG_ARG(tnf, record));
85*7c478bd9Sstevel@tonic-gate }
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate /*
88*7c478bd9Sstevel@tonic-gate  * Retrieve the self_size slot of an ABI array record
89*7c478bd9Sstevel@tonic-gate  */
90*7c478bd9Sstevel@tonic-gate 
91*7c478bd9Sstevel@tonic-gate size_t
92*7c478bd9Sstevel@tonic-gate _tnf_get_self_size(TNF *tnf, tnf_ref32_t *array)
93*7c478bd9Sstevel@tonic-gate {
94*7c478bd9Sstevel@tonic-gate 	return (_GET_SELF_SIZE(tnf, array));
95*7c478bd9Sstevel@tonic-gate }
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate /*
98*7c478bd9Sstevel@tonic-gate  * Calculate the number of elements in ABI array record
99*7c478bd9Sstevel@tonic-gate  */
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate unsigned
102*7c478bd9Sstevel@tonic-gate _tnf_get_element_count(TNF *tnf, tnf_ref32_t *array, unsigned eltsize)
103*7c478bd9Sstevel@tonic-gate {
104*7c478bd9Sstevel@tonic-gate 	size_t		size, hdrsize;
105*7c478bd9Sstevel@tonic-gate #ifdef INFINITE_RECURSION_ARRAY
106*7c478bd9Sstevel@tonic-gate 	tnf_ref32_t	*base_tag;
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate 	size 		= _tnf_get_self_size(tnf, array);
109*7c478bd9Sstevel@tonic-gate 	base_tag 	= _tnf_get_base_tag(tnf, _tnf_get_tag(tnf, array));
110*7c478bd9Sstevel@tonic-gate 	hdrsize		= _tnf_get_header_size(tnf, base_tag);
111*7c478bd9Sstevel@tonic-gate 	return (((size - hdrsize) / eltsize));
112*7c478bd9Sstevel@tonic-gate #else
113*7c478bd9Sstevel@tonic-gate 	size 		= _tnf_get_self_size(tnf, array);
114*7c478bd9Sstevel@tonic-gate 	hdrsize		= sizeof (struct tnf_array_hdr);
115*7c478bd9Sstevel@tonic-gate 	return (((size - hdrsize) / eltsize));
116*7c478bd9Sstevel@tonic-gate #endif
117*7c478bd9Sstevel@tonic-gate }
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate /*
120*7c478bd9Sstevel@tonic-gate  * Retrieve the base pointer of an ABI array record
121*7c478bd9Sstevel@tonic-gate  */
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate caddr_t
124*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
125*7c478bd9Sstevel@tonic-gate _tnf_get_elements(TNF *tnf, tnf_ref32_t *array)
126*7c478bd9Sstevel@tonic-gate {
127*7c478bd9Sstevel@tonic-gate #ifdef INFINITE_RECURSION_ARRAY
128*7c478bd9Sstevel@tonic-gate 	size_t		hdrsize;
129*7c478bd9Sstevel@tonic-gate 	tnf_ref32_t	*base_tag;
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate 	base_tag	= _tnf_get_base_tag(tnf, _tnf_get_tag(tnf, array));
132*7c478bd9Sstevel@tonic-gate 	hdrsize		= _tnf_get_header_size(tnf, base_tag);
133*7c478bd9Sstevel@tonic-gate 	return ((caddr_t)((char *)array + hdrsize));
134*7c478bd9Sstevel@tonic-gate #else
135*7c478bd9Sstevel@tonic-gate 	return ((caddr_t)((char *)array + sizeof (struct tnf_array_hdr)));
136*7c478bd9Sstevel@tonic-gate #endif
137*7c478bd9Sstevel@tonic-gate }
138*7c478bd9Sstevel@tonic-gate 
139*7c478bd9Sstevel@tonic-gate /*
140*7c478bd9Sstevel@tonic-gate  * Retrieve the chars in an ABI string record
141*7c478bd9Sstevel@tonic-gate  */
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate char *
144*7c478bd9Sstevel@tonic-gate _tnf_get_chars(TNF *tnf, tnf_ref32_t *string)
145*7c478bd9Sstevel@tonic-gate {
146*7c478bd9Sstevel@tonic-gate 	return ((char *)_tnf_get_elements(tnf, string));
147*7c478bd9Sstevel@tonic-gate }
148*7c478bd9Sstevel@tonic-gate 
149*7c478bd9Sstevel@tonic-gate /*
150*7c478bd9Sstevel@tonic-gate  * Retrieve the string in the name slot of a type record
151*7c478bd9Sstevel@tonic-gate  */
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate char *
154*7c478bd9Sstevel@tonic-gate _tnf_get_name(TNF *tnf, tnf_ref32_t *tag)
155*7c478bd9Sstevel@tonic-gate {
156*7c478bd9Sstevel@tonic-gate 	return (_tnf_get_chars(tnf, _GET_NAME(tnf, tag)));
157*7c478bd9Sstevel@tonic-gate }
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate /*
160*7c478bd9Sstevel@tonic-gate  * Retrieve the properties array slot of a type record
161*7c478bd9Sstevel@tonic-gate  */
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate tnf_ref32_t *
164*7c478bd9Sstevel@tonic-gate _tnf_get_properties(TNF *tnf, tnf_ref32_t *tag)
165*7c478bd9Sstevel@tonic-gate {
166*7c478bd9Sstevel@tonic-gate 	return (_GET_PROPERTIES(tnf, tag));
167*7c478bd9Sstevel@tonic-gate }
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate /*
170*7c478bd9Sstevel@tonic-gate  * Retrieve the slot_types slot of struct_type or array_type record
171*7c478bd9Sstevel@tonic-gate  */
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate tnf_ref32_t *
174*7c478bd9Sstevel@tonic-gate _tnf_get_slot_types(TNF *tnf, tnf_ref32_t *tag)
175*7c478bd9Sstevel@tonic-gate {
176*7c478bd9Sstevel@tonic-gate 	return (_GET_SLOT_TYPES(tnf, tag));
177*7c478bd9Sstevel@tonic-gate }
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate /*
180*7c478bd9Sstevel@tonic-gate  * Retrieve the header_size slot of an array_type record
181*7c478bd9Sstevel@tonic-gate  */
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate size_t
184*7c478bd9Sstevel@tonic-gate _tnf_get_header_size(TNF *tnf, tnf_ref32_t *tag)
185*7c478bd9Sstevel@tonic-gate {
186*7c478bd9Sstevel@tonic-gate 	return (_GET_HEADER_SIZE(tnf, tag));
187*7c478bd9Sstevel@tonic-gate }
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate /*
190*7c478bd9Sstevel@tonic-gate  * Retrieve the derived_base slot of a derived_type record
191*7c478bd9Sstevel@tonic-gate  */
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate tnf_ref32_t *
194*7c478bd9Sstevel@tonic-gate _tnf_get_derived_base(TNF *tnf, tnf_ref32_t *tag)
195*7c478bd9Sstevel@tonic-gate {
196*7c478bd9Sstevel@tonic-gate 	return (_GET_DERIVED_BASE(tnf, tag));
197*7c478bd9Sstevel@tonic-gate }
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate /*
201*7c478bd9Sstevel@tonic-gate  * Find the root (self-tagged) type record
202*7c478bd9Sstevel@tonic-gate  */
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate tnf_ref32_t *
205*7c478bd9Sstevel@tonic-gate _tnf_get_root_tag(TNF *tnf, tnf_ref32_t *record)
206*7c478bd9Sstevel@tonic-gate {
207*7c478bd9Sstevel@tonic-gate 	if (tnf->root_tag)
208*7c478bd9Sstevel@tonic-gate 		return (tnf->root_tag);
209*7c478bd9Sstevel@tonic-gate 	else {
210*7c478bd9Sstevel@tonic-gate 		tnf_ref32_t	*p1, *p2;
211*7c478bd9Sstevel@tonic-gate 		p1 = record;
212*7c478bd9Sstevel@tonic-gate 		while ((p2 = _tnf_get_tag(tnf, p1)) != p1)
213*7c478bd9Sstevel@tonic-gate 			p1 = p2;
214*7c478bd9Sstevel@tonic-gate 		tnf->root_tag = p2;
215*7c478bd9Sstevel@tonic-gate 		return (p2);
216*7c478bd9Sstevel@tonic-gate 	}
217*7c478bd9Sstevel@tonic-gate }
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate /*
220*7c478bd9Sstevel@tonic-gate  * Search ABI type array for a type named name
221*7c478bd9Sstevel@tonic-gate  */
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate tnf_ref32_t *
224*7c478bd9Sstevel@tonic-gate _tnf_get_element_named(TNF *tnf, tnf_ref32_t *array, char *name)
225*7c478bd9Sstevel@tonic-gate {
226*7c478bd9Sstevel@tonic-gate 	unsigned	count, i;
227*7c478bd9Sstevel@tonic-gate 	tnf_ref32_t	*elts;
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate 	count 	= _tnf_get_element_count(tnf, array, sizeof (tnf_ref32_t));
230*7c478bd9Sstevel@tonic-gate 	/* LINTED pointer cast may result in improper alignment */
231*7c478bd9Sstevel@tonic-gate 	elts	= (tnf_ref32_t *)_tnf_get_elements(tnf, array);
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < count; i++) {
234*7c478bd9Sstevel@tonic-gate 		tnf_ref32_t	*type_elt;
235*7c478bd9Sstevel@tonic-gate 
236*7c478bd9Sstevel@tonic-gate 		if ((type_elt = _GET_REF32(tnf, &elts[i])) == TNF_NULL) {
237*7c478bd9Sstevel@tonic-gate 			/* Can't have missing type records */
238*7c478bd9Sstevel@tonic-gate 			_tnf_error(tnf, TNF_ERR_BADTNF);
239*7c478bd9Sstevel@tonic-gate 			return (TNF_NULL);
240*7c478bd9Sstevel@tonic-gate 		}
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate 		if (strcmp(name, _tnf_get_name(tnf, type_elt)) == 0)
243*7c478bd9Sstevel@tonic-gate 			/* Found a type record named name */
244*7c478bd9Sstevel@tonic-gate 			return (type_elt);
245*7c478bd9Sstevel@tonic-gate 	}
246*7c478bd9Sstevel@tonic-gate 	return (TNF_NULL);
247*7c478bd9Sstevel@tonic-gate }
248*7c478bd9Sstevel@tonic-gate 
249*7c478bd9Sstevel@tonic-gate /*
250*7c478bd9Sstevel@tonic-gate  * Look in type record's properties for named type.
251*7c478bd9Sstevel@tonic-gate  * Recursively look at derived_base properties as well.
252*7c478bd9Sstevel@tonic-gate  */
253*7c478bd9Sstevel@tonic-gate 
254*7c478bd9Sstevel@tonic-gate tnf_ref32_t *
255*7c478bd9Sstevel@tonic-gate _tnf_get_property(TNF *tnf, tnf_ref32_t *tag, char *name)
256*7c478bd9Sstevel@tonic-gate {
257*7c478bd9Sstevel@tonic-gate 	tnf_ref32_t	*properties, *property;
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate 	if (strcmp(name, _tnf_get_name(tnf, tag)) == 0)
260*7c478bd9Sstevel@tonic-gate 		/* name is type name */
261*7c478bd9Sstevel@tonic-gate 		return (tag);
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate 	if ((properties = _tnf_get_properties(tnf, tag)) == TNF_NULL)
264*7c478bd9Sstevel@tonic-gate 		/* no properties */
265*7c478bd9Sstevel@tonic-gate 		return (TNF_NULL);
266*7c478bd9Sstevel@tonic-gate 
267*7c478bd9Sstevel@tonic-gate 	if ((property = _tnf_get_element_named(tnf, properties, name))
268*7c478bd9Sstevel@tonic-gate 	    != TNF_NULL)
269*7c478bd9Sstevel@tonic-gate 		/* found property named name */
270*7c478bd9Sstevel@tonic-gate 		return (property);
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate 	/*
273*7c478bd9Sstevel@tonic-gate 	 * Recursively check base type of derived types
274*7c478bd9Sstevel@tonic-gate 	 */
275*7c478bd9Sstevel@tonic-gate 	if (_tnf_get_element_named(tnf, properties, TNF_N_DERIVED)
276*7c478bd9Sstevel@tonic-gate 	    != TNF_NULL) {
277*7c478bd9Sstevel@tonic-gate 		/* tag is a derived type: check its derived_base */
278*7c478bd9Sstevel@tonic-gate 		tnf_ref32_t	*base_tag;
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate 		base_tag = _tnf_get_derived_base(tnf, tag);
281*7c478bd9Sstevel@tonic-gate 		/* tnf_derived has derived_base == TNF_NULL */
282*7c478bd9Sstevel@tonic-gate 		if (base_tag != TNF_NULL)
283*7c478bd9Sstevel@tonic-gate 			return (_tnf_get_property(tnf, base_tag, name));
284*7c478bd9Sstevel@tonic-gate 	}
285*7c478bd9Sstevel@tonic-gate 
286*7c478bd9Sstevel@tonic-gate 	return (TNF_NULL);
287*7c478bd9Sstevel@tonic-gate }
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate /*
290*7c478bd9Sstevel@tonic-gate  * Get the ultimate base type of a type record
291*7c478bd9Sstevel@tonic-gate  */
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate tnf_ref32_t *
294*7c478bd9Sstevel@tonic-gate _tnf_get_base_tag(TNF *tnf, tnf_ref32_t *tag)
295*7c478bd9Sstevel@tonic-gate {
296*7c478bd9Sstevel@tonic-gate 	tnf_ref32_t	*properties;
297*7c478bd9Sstevel@tonic-gate 
298*7c478bd9Sstevel@tonic-gate 	if ((properties = _tnf_get_properties(tnf, tag)) == TNF_NULL)
299*7c478bd9Sstevel@tonic-gate 		/* no properties */
300*7c478bd9Sstevel@tonic-gate 		return (tag);
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate 	if (_tnf_get_element_named(tnf, properties, TNF_N_DERIVED)
303*7c478bd9Sstevel@tonic-gate 	    != TNF_NULL) {
304*7c478bd9Sstevel@tonic-gate 		tnf_ref32_t	*base_tag;
305*7c478bd9Sstevel@tonic-gate 
306*7c478bd9Sstevel@tonic-gate 		if ((base_tag = _tnf_get_derived_base(tnf, tag)) != TNF_NULL)
307*7c478bd9Sstevel@tonic-gate 			return (_tnf_get_base_tag(tnf, base_tag));
308*7c478bd9Sstevel@tonic-gate 	}
309*7c478bd9Sstevel@tonic-gate 
310*7c478bd9Sstevel@tonic-gate 	return (tag);
311*7c478bd9Sstevel@tonic-gate }
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate /*
314*7c478bd9Sstevel@tonic-gate  * Calculate the reference size of an object with type==tag
315*7c478bd9Sstevel@tonic-gate  */
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate size_t
318*7c478bd9Sstevel@tonic-gate _tnf_get_ref_size(TNF *tnf, tnf_ref32_t *tag)
319*7c478bd9Sstevel@tonic-gate {
320*7c478bd9Sstevel@tonic-gate 	if (HAS_PROPERTY(tnf, tag, TNF_N_TAGGED)) {
321*7c478bd9Sstevel@tonic-gate 		/* Tagged objects occupy 4 bytes for reference */
322*7c478bd9Sstevel@tonic-gate 		return ((sizeof (tnf_ref32_t)));
323*7c478bd9Sstevel@tonic-gate 	} else if (HAS_PROPERTY(tnf, tag, TNF_N_INLINE)) {
324*7c478bd9Sstevel@tonic-gate 		/* Inline slots cannot be self sized */
325*7c478bd9Sstevel@tonic-gate 		return (_tnf_get_storage_size(tnf, tag));
326*7c478bd9Sstevel@tonic-gate 	} else {
327*7c478bd9Sstevel@tonic-gate 		/* Illegal to have references to abstract objects */
328*7c478bd9Sstevel@tonic-gate 		_tnf_error(tnf, TNF_ERR_BADTNF);
329*7c478bd9Sstevel@tonic-gate 		return ((0));
330*7c478bd9Sstevel@tonic-gate 	}
331*7c478bd9Sstevel@tonic-gate }
332*7c478bd9Sstevel@tonic-gate 
333*7c478bd9Sstevel@tonic-gate /*
334*7c478bd9Sstevel@tonic-gate  * Calculate storage size of an object with type==tag
335*7c478bd9Sstevel@tonic-gate  */
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate size_t
338*7c478bd9Sstevel@tonic-gate _tnf_get_storage_size(TNF *tnf, tnf_ref32_t *tag)
339*7c478bd9Sstevel@tonic-gate {
340*7c478bd9Sstevel@tonic-gate 	if (_tnf_get_tag(tnf, tag) == _tnf_get_root_tag(tnf, tag))
341*7c478bd9Sstevel@tonic-gate 		return (_GET_TYPE_SIZE(tnf, tag));
342*7c478bd9Sstevel@tonic-gate 	else {
343*7c478bd9Sstevel@tonic-gate 		tnf_ref32_t	*base_tag; /* implementation tag */
344*7c478bd9Sstevel@tonic-gate 		caddr_t		sizep;
345*7c478bd9Sstevel@tonic-gate 		tnf_ref32_t	*slot_types;
346*7c478bd9Sstevel@tonic-gate 
347*7c478bd9Sstevel@tonic-gate #ifndef INFINITE_RECURSION_SIZE
348*7c478bd9Sstevel@tonic-gate 		char		*base_name;
349*7c478bd9Sstevel@tonic-gate 		static struct n2s {
350*7c478bd9Sstevel@tonic-gate 			char	*name;
351*7c478bd9Sstevel@tonic-gate 			size_t	size;
352*7c478bd9Sstevel@tonic-gate 		} n2s[] = {
353*7c478bd9Sstevel@tonic-gate 		{ TNF_N_CHAR, 		sizeof (tnf_char_t) },
354*7c478bd9Sstevel@tonic-gate 		{ TNF_N_INT8,		sizeof (tnf_int8_t) },
355*7c478bd9Sstevel@tonic-gate 		{ TNF_N_INT16,		sizeof (tnf_int16_t) },
356*7c478bd9Sstevel@tonic-gate 		{ TNF_N_INT32,		sizeof (tnf_int32_t) },
357*7c478bd9Sstevel@tonic-gate 		{ TNF_N_UINT8,		sizeof (tnf_uint8_t) },
358*7c478bd9Sstevel@tonic-gate 		{ TNF_N_UINT16,		sizeof (tnf_uint16_t) },
359*7c478bd9Sstevel@tonic-gate 		{ TNF_N_UINT32,		sizeof (tnf_uint32_t) },
360*7c478bd9Sstevel@tonic-gate 		{ TNF_N_INT64,		sizeof (tnf_int64_t) },
361*7c478bd9Sstevel@tonic-gate 		{ TNF_N_UINT64,		sizeof (tnf_uint64_t) },
362*7c478bd9Sstevel@tonic-gate 		{ TNF_N_FLOAT32,	sizeof (tnf_float32_t) },
363*7c478bd9Sstevel@tonic-gate 		{ TNF_N_FLOAT64,	sizeof (tnf_float64_t) },
364*7c478bd9Sstevel@tonic-gate 		{ NULL,			0 }
365*7c478bd9Sstevel@tonic-gate 		};
366*7c478bd9Sstevel@tonic-gate 		struct n2s	*p;
367*7c478bd9Sstevel@tonic-gate #endif
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate 		base_tag 	= _tnf_get_base_tag(tnf, tag);
370*7c478bd9Sstevel@tonic-gate 
371*7c478bd9Sstevel@tonic-gate #ifndef INFINITE_RECURSION_SIZE
372*7c478bd9Sstevel@tonic-gate 		base_name 	= _tnf_get_name(tnf, base_tag);
373*7c478bd9Sstevel@tonic-gate 
374*7c478bd9Sstevel@tonic-gate 		/* XXX Why are we in this mess? */
375*7c478bd9Sstevel@tonic-gate 		p = n2s;
376*7c478bd9Sstevel@tonic-gate 		while (p->name) {
377*7c478bd9Sstevel@tonic-gate 			if (strcmp(p->name, base_name) == 0)
378*7c478bd9Sstevel@tonic-gate 				return (p->size);
379*7c478bd9Sstevel@tonic-gate 			p++;
380*7c478bd9Sstevel@tonic-gate 		}
381*7c478bd9Sstevel@tonic-gate #endif
382*7c478bd9Sstevel@tonic-gate 
383*7c478bd9Sstevel@tonic-gate 		sizep = _tnf_get_slot_typed(tnf, base_tag, TNF_N_TYPE_SIZE);
384*7c478bd9Sstevel@tonic-gate 		if (sizep)
385*7c478bd9Sstevel@tonic-gate 			/* Type sized */
386*7c478bd9Sstevel@tonic-gate 		/* LINTED pointer cast may result in improper alignment */
387*7c478bd9Sstevel@tonic-gate 			return (_GET_UINT32(tnf, (tnf_uint32_t *)sizep));
388*7c478bd9Sstevel@tonic-gate 
389*7c478bd9Sstevel@tonic-gate 		slot_types = (tnf_ref32_t *)
390*7c478bd9Sstevel@tonic-gate 		/* LINTED pointer cast may result in improper alignment */
391*7c478bd9Sstevel@tonic-gate 		    _tnf_get_slot_typed(tnf, base_tag, TNF_N_SLOT_TYPES);
392*7c478bd9Sstevel@tonic-gate 		if (slot_types &&
393*7c478bd9Sstevel@tonic-gate 		    _tnf_get_element_named(tnf, slot_types, TNF_N_SELF_SIZE))
394*7c478bd9Sstevel@tonic-gate 			/* Self sized */
395*7c478bd9Sstevel@tonic-gate 			return ((size_t)-1);
396*7c478bd9Sstevel@tonic-gate 		else
397*7c478bd9Sstevel@tonic-gate 			/* Abstract */
398*7c478bd9Sstevel@tonic-gate 			return (0);
399*7c478bd9Sstevel@tonic-gate 	}
400*7c478bd9Sstevel@tonic-gate }
401*7c478bd9Sstevel@tonic-gate 
402*7c478bd9Sstevel@tonic-gate /*
403*7c478bd9Sstevel@tonic-gate  * Return the alignment restriction for any tag
404*7c478bd9Sstevel@tonic-gate  */
405*7c478bd9Sstevel@tonic-gate 
406*7c478bd9Sstevel@tonic-gate unsigned
407*7c478bd9Sstevel@tonic-gate _tnf_get_align(TNF *tnf, tnf_ref32_t *tag)
408*7c478bd9Sstevel@tonic-gate {
409*7c478bd9Sstevel@tonic-gate 	if (HAS_PROPERTY(tnf, tag, TNF_N_SCALAR)) {
410*7c478bd9Sstevel@tonic-gate 		tnf_ref32_t	*base_tag;
411*7c478bd9Sstevel@tonic-gate 		caddr_t		alignp;
412*7c478bd9Sstevel@tonic-gate 
413*7c478bd9Sstevel@tonic-gate 		base_tag = _tnf_get_base_tag(tnf, tag);
414*7c478bd9Sstevel@tonic-gate 		alignp   = _tnf_get_slot_typed(tnf, base_tag, TNF_N_ALIGN);
415*7c478bd9Sstevel@tonic-gate 		if (alignp)
416*7c478bd9Sstevel@tonic-gate 		/* LINTED pointer cast may result in improper alignment */
417*7c478bd9Sstevel@tonic-gate 			return (_GET_UINT32(tnf, (tnf_uint32_t *)alignp));
418*7c478bd9Sstevel@tonic-gate 	}
419*7c478bd9Sstevel@tonic-gate 	/* default: word alignment */
420*7c478bd9Sstevel@tonic-gate 	return ((4));
421*7c478bd9Sstevel@tonic-gate }
422*7c478bd9Sstevel@tonic-gate 
423*7c478bd9Sstevel@tonic-gate /*
424*7c478bd9Sstevel@tonic-gate  * Only works for records
425*7c478bd9Sstevel@tonic-gate  * Doesn't check for slot_names in tag
426*7c478bd9Sstevel@tonic-gate  * Tag records, for example, never have named slots
427*7c478bd9Sstevel@tonic-gate  */
428*7c478bd9Sstevel@tonic-gate 
429*7c478bd9Sstevel@tonic-gate caddr_t
430*7c478bd9Sstevel@tonic-gate _tnf_get_slot_typed(TNF *tnf, tnf_ref32_t *record, char *name)
431*7c478bd9Sstevel@tonic-gate {
432*7c478bd9Sstevel@tonic-gate 	tnf_ref32_t 	*tag, *base_tag;
433*7c478bd9Sstevel@tonic-gate 	tnf_ref32_t	*slot_types, *types;
434*7c478bd9Sstevel@tonic-gate 	unsigned	count, i;
435*7c478bd9Sstevel@tonic-gate 	unsigned 	offset;
436*7c478bd9Sstevel@tonic-gate 
437*7c478bd9Sstevel@tonic-gate 	tag 		= _tnf_get_tag(tnf, record);
438*7c478bd9Sstevel@tonic-gate 	base_tag 	= _tnf_get_base_tag(tnf, tag);
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate 	/*
441*7c478bd9Sstevel@tonic-gate 	 * The position of slot_types is ABI fixed
442*7c478bd9Sstevel@tonic-gate 	 * XXX Assume it is present in tag
443*7c478bd9Sstevel@tonic-gate 	 */
444*7c478bd9Sstevel@tonic-gate 	slot_types = _tnf_get_slot_types(tnf, base_tag);
445*7c478bd9Sstevel@tonic-gate 	count = _tnf_get_element_count(tnf, slot_types, sizeof (tnf_ref32_t));
446*7c478bd9Sstevel@tonic-gate 	/* LINTED pointer cast may result in improper alignment */
447*7c478bd9Sstevel@tonic-gate 	types = (tnf_ref32_t *)_tnf_get_elements(tnf, slot_types);
448*7c478bd9Sstevel@tonic-gate 
449*7c478bd9Sstevel@tonic-gate 	offset 	= 0;
450*7c478bd9Sstevel@tonic-gate 
451*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < count; i++) {
452*7c478bd9Sstevel@tonic-gate 		tnf_ref32_t	*type_elt;
453*7c478bd9Sstevel@tonic-gate 		size_t		ref_size, align;
454*7c478bd9Sstevel@tonic-gate 
455*7c478bd9Sstevel@tonic-gate 		/* Find the type record for slot */
456*7c478bd9Sstevel@tonic-gate 		if ((type_elt = _GET_REF32(tnf, &types[i])) == TNF_NULL) {
457*7c478bd9Sstevel@tonic-gate 			/* Can't have missing type records */
458*7c478bd9Sstevel@tonic-gate 			_tnf_error(tnf, TNF_ERR_BADTNF);
459*7c478bd9Sstevel@tonic-gate 			return ((caddr_t)NULL);
460*7c478bd9Sstevel@tonic-gate 		}
461*7c478bd9Sstevel@tonic-gate 
462*7c478bd9Sstevel@tonic-gate 		/* See similar hack in init_slots() */
463*7c478bd9Sstevel@tonic-gate 
464*7c478bd9Sstevel@tonic-gate 		/* Calculate reference size */
465*7c478bd9Sstevel@tonic-gate 		ref_size = _tnf_get_ref_size(tnf, type_elt);
466*7c478bd9Sstevel@tonic-gate 
467*7c478bd9Sstevel@tonic-gate 		/*
468*7c478bd9Sstevel@tonic-gate 		 * Calculate alignment
469*7c478bd9Sstevel@tonic-gate 		 * XXX Prevent infinite recursion by assuming that
470*7c478bd9Sstevel@tonic-gate 		 * a reference size of 4 implies word alignment
471*7c478bd9Sstevel@tonic-gate 		 */
472*7c478bd9Sstevel@tonic-gate 		align = (ref_size == 4)? 4: _tnf_get_align(tnf, type_elt);
473*7c478bd9Sstevel@tonic-gate 
474*7c478bd9Sstevel@tonic-gate 		/* Adjust offset to account for alignment, if needed */
475*7c478bd9Sstevel@tonic-gate 		offset = ALIGN(offset, align);
476*7c478bd9Sstevel@tonic-gate 
477*7c478bd9Sstevel@tonic-gate 		/* Check whether name corresponds to type name */
478*7c478bd9Sstevel@tonic-gate 		if (strcmp(name, _tnf_get_name(tnf, type_elt)) == 0)
479*7c478bd9Sstevel@tonic-gate 			/* Found the slot */
480*7c478bd9Sstevel@tonic-gate 			return (fetch_slot(tnf, (caddr_t)record + offset,
481*7c478bd9Sstevel@tonic-gate 					type_elt));
482*7c478bd9Sstevel@tonic-gate 
483*7c478bd9Sstevel@tonic-gate 		/* Bump offset by reference size */
484*7c478bd9Sstevel@tonic-gate 		offset += ref_size;
485*7c478bd9Sstevel@tonic-gate 	}
486*7c478bd9Sstevel@tonic-gate 
487*7c478bd9Sstevel@tonic-gate 	return ((caddr_t)NULL);
488*7c478bd9Sstevel@tonic-gate }
489*7c478bd9Sstevel@tonic-gate 
490*7c478bd9Sstevel@tonic-gate /*
491*7c478bd9Sstevel@tonic-gate  * Only works for records
492*7c478bd9Sstevel@tonic-gate  */
493*7c478bd9Sstevel@tonic-gate 
494*7c478bd9Sstevel@tonic-gate caddr_t
495*7c478bd9Sstevel@tonic-gate _tnf_get_slot_named(TNF *tnf, tnf_ref32_t *record, char *name)
496*7c478bd9Sstevel@tonic-gate {
497*7c478bd9Sstevel@tonic-gate 	tnf_ref32_t 	*tag, *base_tag;
498*7c478bd9Sstevel@tonic-gate 	tnf_ref32_t	*slot_types, *slot_names, *types, *names;
499*7c478bd9Sstevel@tonic-gate 	unsigned	count, i;
500*7c478bd9Sstevel@tonic-gate 	unsigned 	offset;
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate 	tag 		= _tnf_get_tag(tnf, record);
503*7c478bd9Sstevel@tonic-gate 	base_tag 	= _tnf_get_base_tag(tnf, tag);
504*7c478bd9Sstevel@tonic-gate 
505*7c478bd9Sstevel@tonic-gate 	/*
506*7c478bd9Sstevel@tonic-gate 	 * slot_names are optional
507*7c478bd9Sstevel@tonic-gate 	 */
508*7c478bd9Sstevel@tonic-gate 	slot_names = (tnf_ref32_t *)
509*7c478bd9Sstevel@tonic-gate 		/* LINTED pointer cast may result in improper alignment */
510*7c478bd9Sstevel@tonic-gate 	    _tnf_get_slot_typed(tnf, base_tag, TNF_N_SLOT_NAMES);
511*7c478bd9Sstevel@tonic-gate 
512*7c478bd9Sstevel@tonic-gate 	/* no slot_names; use _tnf_get_slot_typed() */
513*7c478bd9Sstevel@tonic-gate 	if (slot_names == TNF_NULL)
514*7c478bd9Sstevel@tonic-gate 		return (_tnf_get_slot_typed(tnf, record, name));
515*7c478bd9Sstevel@tonic-gate 
516*7c478bd9Sstevel@tonic-gate 	/*
517*7c478bd9Sstevel@tonic-gate 	 * The position of slot_types is ABI fixed
518*7c478bd9Sstevel@tonic-gate 	 * XXX Assume it is present in tag
519*7c478bd9Sstevel@tonic-gate 	 */
520*7c478bd9Sstevel@tonic-gate 	slot_types = _tnf_get_slot_types(tnf, base_tag);
521*7c478bd9Sstevel@tonic-gate 	count = _tnf_get_element_count(tnf, slot_types, sizeof (tnf_ref32_t));
522*7c478bd9Sstevel@tonic-gate 	/* LINTED pointer cast may result in improper alignment */
523*7c478bd9Sstevel@tonic-gate 	types = (tnf_ref32_t *)_tnf_get_elements(tnf, slot_types);
524*7c478bd9Sstevel@tonic-gate 	/* LINTED pointer cast may result in improper alignment */
525*7c478bd9Sstevel@tonic-gate 	names = (tnf_ref32_t *)_tnf_get_elements(tnf, slot_names);
526*7c478bd9Sstevel@tonic-gate 
527*7c478bd9Sstevel@tonic-gate 	offset 	= 0;
528*7c478bd9Sstevel@tonic-gate 
529*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < count; i++) {
530*7c478bd9Sstevel@tonic-gate 		tnf_ref32_t	*type_elt, *name_elt;
531*7c478bd9Sstevel@tonic-gate 		size_t		ref_size, align;
532*7c478bd9Sstevel@tonic-gate 
533*7c478bd9Sstevel@tonic-gate 		/* Find the type record for slot */
534*7c478bd9Sstevel@tonic-gate 		if ((type_elt = _GET_REF32(tnf, &types[i])) == TNF_NULL) {
535*7c478bd9Sstevel@tonic-gate 			/* Can't have missing type records */
536*7c478bd9Sstevel@tonic-gate 			_tnf_error(tnf, TNF_ERR_BADTNF);
537*7c478bd9Sstevel@tonic-gate 			return ((caddr_t)NULL);
538*7c478bd9Sstevel@tonic-gate 		}
539*7c478bd9Sstevel@tonic-gate 
540*7c478bd9Sstevel@tonic-gate 		/* XXX Keep consistent with init_slots() */
541*7c478bd9Sstevel@tonic-gate 
542*7c478bd9Sstevel@tonic-gate 		/* Calculate reference size */
543*7c478bd9Sstevel@tonic-gate 		ref_size = _tnf_get_ref_size(tnf, type_elt);
544*7c478bd9Sstevel@tonic-gate 
545*7c478bd9Sstevel@tonic-gate 		/*
546*7c478bd9Sstevel@tonic-gate 		 * Calculate alignment
547*7c478bd9Sstevel@tonic-gate 		 * XXX Prevent infinite recursion by assuming that
548*7c478bd9Sstevel@tonic-gate 		 * a reference size of 4 implies word alignment
549*7c478bd9Sstevel@tonic-gate 		 */
550*7c478bd9Sstevel@tonic-gate 		align = (ref_size == 4)? 4: _tnf_get_align(tnf, type_elt);
551*7c478bd9Sstevel@tonic-gate 
552*7c478bd9Sstevel@tonic-gate 		/* Adjust offset to account for alignment, if needed */
553*7c478bd9Sstevel@tonic-gate 		offset = ALIGN(offset, align);
554*7c478bd9Sstevel@tonic-gate 
555*7c478bd9Sstevel@tonic-gate 		/* First check slot name, then type name */
556*7c478bd9Sstevel@tonic-gate 		if ((((name_elt = _GET_REF32(tnf, &names[i])) != TNF_NULL) &&
557*7c478bd9Sstevel@tonic-gate 			(strcmp(name, _tnf_get_chars(tnf, name_elt)) == 0)) ||
558*7c478bd9Sstevel@tonic-gate 			(strcmp(name, _tnf_get_name(tnf, type_elt)) == 0))
559*7c478bd9Sstevel@tonic-gate 			/* Found slot */
560*7c478bd9Sstevel@tonic-gate 			return (fetch_slot(tnf, (caddr_t)record + offset,
561*7c478bd9Sstevel@tonic-gate 				    type_elt));
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate 		/* Bump offset by reference size */
564*7c478bd9Sstevel@tonic-gate 		offset += ref_size;
565*7c478bd9Sstevel@tonic-gate 	}
566*7c478bd9Sstevel@tonic-gate 
567*7c478bd9Sstevel@tonic-gate 	return ((caddr_t)NULL);
568*7c478bd9Sstevel@tonic-gate }
569*7c478bd9Sstevel@tonic-gate 
570*7c478bd9Sstevel@tonic-gate static caddr_t
571*7c478bd9Sstevel@tonic-gate fetch_slot(TNF *tnf, caddr_t p, tnf_ref32_t *tag)
572*7c478bd9Sstevel@tonic-gate {
573*7c478bd9Sstevel@tonic-gate 	if (HAS_PROPERTY(tnf, tag, TNF_N_INLINE))
574*7c478bd9Sstevel@tonic-gate 		return (p);
575*7c478bd9Sstevel@tonic-gate 	else			/* XXX assume tagged */
576*7c478bd9Sstevel@tonic-gate 		/* LINTED pointer cast may result in improper alignment */
577*7c478bd9Sstevel@tonic-gate 		return ((caddr_t)_GET_REF32(tnf, (tnf_ref32_t *)p));
578*7c478bd9Sstevel@tonic-gate }
579