xref: /titanic_54/usr/src/common/ctf/ctf_open.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 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <ctf_impl.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/mman.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/zmod.h>
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate static const ctf_dmodel_t _libctf_models[] = {
34*7c478bd9Sstevel@tonic-gate 	{ "ILP32", CTF_MODEL_ILP32, 4, 1, 2, 4, 4 },
35*7c478bd9Sstevel@tonic-gate 	{ "LP64", CTF_MODEL_LP64, 8, 1, 2, 4, 8 },
36*7c478bd9Sstevel@tonic-gate 	{ NULL, 0, 0, 0, 0, 0, 0 }
37*7c478bd9Sstevel@tonic-gate };
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate const char _CTF_SECTION[] = ".SUNW_ctf";
40*7c478bd9Sstevel@tonic-gate const char _CTF_NULLSTR[] = "";
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate int _libctf_version = CTF_VERSION;	/* library client version */
43*7c478bd9Sstevel@tonic-gate int _libctf_debug = 0;			/* debugging messages enabled */
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate static ushort_t
46*7c478bd9Sstevel@tonic-gate get_kind_v1(ushort_t info)
47*7c478bd9Sstevel@tonic-gate {
48*7c478bd9Sstevel@tonic-gate 	return (CTF_INFO_KIND_V1(info));
49*7c478bd9Sstevel@tonic-gate }
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate static ushort_t
52*7c478bd9Sstevel@tonic-gate get_kind_v2(ushort_t info)
53*7c478bd9Sstevel@tonic-gate {
54*7c478bd9Sstevel@tonic-gate 	return (CTF_INFO_KIND(info));
55*7c478bd9Sstevel@tonic-gate }
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate static ushort_t
58*7c478bd9Sstevel@tonic-gate get_root_v1(ushort_t info)
59*7c478bd9Sstevel@tonic-gate {
60*7c478bd9Sstevel@tonic-gate 	return (CTF_INFO_ISROOT_V1(info));
61*7c478bd9Sstevel@tonic-gate }
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate static ushort_t
64*7c478bd9Sstevel@tonic-gate get_root_v2(ushort_t info)
65*7c478bd9Sstevel@tonic-gate {
66*7c478bd9Sstevel@tonic-gate 	return (CTF_INFO_ISROOT(info));
67*7c478bd9Sstevel@tonic-gate }
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate static ushort_t
70*7c478bd9Sstevel@tonic-gate get_vlen_v1(ushort_t info)
71*7c478bd9Sstevel@tonic-gate {
72*7c478bd9Sstevel@tonic-gate 	return (CTF_INFO_VLEN_V1(info));
73*7c478bd9Sstevel@tonic-gate }
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate static ushort_t
76*7c478bd9Sstevel@tonic-gate get_vlen_v2(ushort_t info)
77*7c478bd9Sstevel@tonic-gate {
78*7c478bd9Sstevel@tonic-gate 	return (CTF_INFO_VLEN(info));
79*7c478bd9Sstevel@tonic-gate }
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate static const ctf_fileops_t ctf_fileops[] = {
82*7c478bd9Sstevel@tonic-gate 	{ NULL, NULL },
83*7c478bd9Sstevel@tonic-gate 	{ get_kind_v1, get_root_v1, get_vlen_v1 },
84*7c478bd9Sstevel@tonic-gate 	{ get_kind_v2, get_root_v2, get_vlen_v2 },
85*7c478bd9Sstevel@tonic-gate };
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate /*
88*7c478bd9Sstevel@tonic-gate  * Convert a 32-bit ELF symbol into GElf (Elf64) and return a pointer to it.
89*7c478bd9Sstevel@tonic-gate  */
90*7c478bd9Sstevel@tonic-gate static Elf64_Sym *
91*7c478bd9Sstevel@tonic-gate sym_to_gelf(const Elf32_Sym *src, Elf64_Sym *dst)
92*7c478bd9Sstevel@tonic-gate {
93*7c478bd9Sstevel@tonic-gate 	dst->st_name = src->st_name;
94*7c478bd9Sstevel@tonic-gate 	dst->st_value = src->st_value;
95*7c478bd9Sstevel@tonic-gate 	dst->st_size = src->st_size;
96*7c478bd9Sstevel@tonic-gate 	dst->st_info = src->st_info;
97*7c478bd9Sstevel@tonic-gate 	dst->st_other = src->st_other;
98*7c478bd9Sstevel@tonic-gate 	dst->st_shndx = src->st_shndx;
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate 	return (dst);
101*7c478bd9Sstevel@tonic-gate }
102*7c478bd9Sstevel@tonic-gate 
103*7c478bd9Sstevel@tonic-gate /*
104*7c478bd9Sstevel@tonic-gate  * Initialize the symtab translation table by filling each entry with the
105*7c478bd9Sstevel@tonic-gate  * offset of the CTF type or function data corresponding to each STT_FUNC or
106*7c478bd9Sstevel@tonic-gate  * STT_OBJECT entry in the symbol table.
107*7c478bd9Sstevel@tonic-gate  */
108*7c478bd9Sstevel@tonic-gate static int
109*7c478bd9Sstevel@tonic-gate init_symtab(ctf_file_t *fp, const ctf_header_t *hp,
110*7c478bd9Sstevel@tonic-gate     const ctf_sect_t *sp, const ctf_sect_t *strp)
111*7c478bd9Sstevel@tonic-gate {
112*7c478bd9Sstevel@tonic-gate 	const uchar_t *symp = sp->cts_data;
113*7c478bd9Sstevel@tonic-gate 	uint_t *xp = fp->ctf_sxlate;
114*7c478bd9Sstevel@tonic-gate 	uint_t *xend = xp + fp->ctf_nsyms;
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate 	uint_t objtoff = hp->cth_objtoff;
117*7c478bd9Sstevel@tonic-gate 	uint_t funcoff = hp->cth_funcoff;
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate 	ushort_t info, vlen;
120*7c478bd9Sstevel@tonic-gate 	Elf64_Sym sym, *gsp;
121*7c478bd9Sstevel@tonic-gate 	const char *name;
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate 	/*
124*7c478bd9Sstevel@tonic-gate 	 * The CTF data object and function type sections are ordered to match
125*7c478bd9Sstevel@tonic-gate 	 * the relative order of the respective symbol types in the symtab.
126*7c478bd9Sstevel@tonic-gate 	 * If no type information is available for a symbol table entry, a
127*7c478bd9Sstevel@tonic-gate 	 * pad is inserted in the CTF section.  As a further optimization,
128*7c478bd9Sstevel@tonic-gate 	 * anonymous or undefined symbols are omitted from the CTF data.
129*7c478bd9Sstevel@tonic-gate 	 */
130*7c478bd9Sstevel@tonic-gate 	for (; xp < xend; xp++, symp += sp->cts_entsize) {
131*7c478bd9Sstevel@tonic-gate 		if (sp->cts_entsize == sizeof (Elf32_Sym))
132*7c478bd9Sstevel@tonic-gate 			gsp = sym_to_gelf((Elf32_Sym *)(uintptr_t)symp, &sym);
133*7c478bd9Sstevel@tonic-gate 		else
134*7c478bd9Sstevel@tonic-gate 			gsp = (Elf64_Sym *)(uintptr_t)symp;
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate 		if (gsp->st_name < strp->cts_size)
137*7c478bd9Sstevel@tonic-gate 			name = (const char *)strp->cts_data + gsp->st_name;
138*7c478bd9Sstevel@tonic-gate 		else
139*7c478bd9Sstevel@tonic-gate 			name = _CTF_NULLSTR;
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate 		if (gsp->st_name == 0 || gsp->st_shndx == SHN_UNDEF ||
142*7c478bd9Sstevel@tonic-gate 		    strcmp(name, "_START_") == 0 ||
143*7c478bd9Sstevel@tonic-gate 		    strcmp(name, "_END_") == 0) {
144*7c478bd9Sstevel@tonic-gate 			*xp = -1u;
145*7c478bd9Sstevel@tonic-gate 			continue;
146*7c478bd9Sstevel@tonic-gate 		}
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate 		switch (ELF64_ST_TYPE(gsp->st_info)) {
149*7c478bd9Sstevel@tonic-gate 		case STT_OBJECT:
150*7c478bd9Sstevel@tonic-gate 			if (objtoff >= hp->cth_funcoff ||
151*7c478bd9Sstevel@tonic-gate 			    (gsp->st_shndx == SHN_ABS && gsp->st_value == 0)) {
152*7c478bd9Sstevel@tonic-gate 				*xp = -1u;
153*7c478bd9Sstevel@tonic-gate 				break;
154*7c478bd9Sstevel@tonic-gate 			}
155*7c478bd9Sstevel@tonic-gate 
156*7c478bd9Sstevel@tonic-gate 			*xp = objtoff;
157*7c478bd9Sstevel@tonic-gate 			objtoff += sizeof (ushort_t);
158*7c478bd9Sstevel@tonic-gate 			break;
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate 		case STT_FUNC:
161*7c478bd9Sstevel@tonic-gate 			if (funcoff >= hp->cth_typeoff) {
162*7c478bd9Sstevel@tonic-gate 				*xp = -1u;
163*7c478bd9Sstevel@tonic-gate 				break;
164*7c478bd9Sstevel@tonic-gate 			}
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate 			*xp = funcoff;
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate 			info = *(ushort_t *)((uintptr_t)fp->ctf_buf + funcoff);
169*7c478bd9Sstevel@tonic-gate 			vlen = LCTF_INFO_VLEN(fp, info);
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate 			/*
172*7c478bd9Sstevel@tonic-gate 			 * If we encounter a zero pad at the end, just skip it.
173*7c478bd9Sstevel@tonic-gate 			 * Otherwise skip over the function and its return type
174*7c478bd9Sstevel@tonic-gate 			 * (+2) and the argument list (vlen).
175*7c478bd9Sstevel@tonic-gate 			 */
176*7c478bd9Sstevel@tonic-gate 			if (LCTF_INFO_KIND(fp, info) == CTF_K_UNKNOWN &&
177*7c478bd9Sstevel@tonic-gate 			    vlen == 0)
178*7c478bd9Sstevel@tonic-gate 				funcoff += sizeof (ushort_t); /* skip pad */
179*7c478bd9Sstevel@tonic-gate 			else
180*7c478bd9Sstevel@tonic-gate 				funcoff += sizeof (ushort_t) * (vlen + 2);
181*7c478bd9Sstevel@tonic-gate 			break;
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 		default:
184*7c478bd9Sstevel@tonic-gate 			*xp = -1u;
185*7c478bd9Sstevel@tonic-gate 			break;
186*7c478bd9Sstevel@tonic-gate 		}
187*7c478bd9Sstevel@tonic-gate 	}
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate 	ctf_dprintf("loaded %lu symtab entries\n", fp->ctf_nsyms);
190*7c478bd9Sstevel@tonic-gate 	return (0);
191*7c478bd9Sstevel@tonic-gate }
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate /*
194*7c478bd9Sstevel@tonic-gate  * Initialize the type ID translation table with the byte offset of each type,
195*7c478bd9Sstevel@tonic-gate  * and initialize the hash tables of each named type.
196*7c478bd9Sstevel@tonic-gate  */
197*7c478bd9Sstevel@tonic-gate static int
198*7c478bd9Sstevel@tonic-gate init_types(ctf_file_t *fp, const ctf_header_t *hp)
199*7c478bd9Sstevel@tonic-gate {
200*7c478bd9Sstevel@tonic-gate 	/* LINTED - pointer alignment */
201*7c478bd9Sstevel@tonic-gate 	const ctf_type_t *tbuf = (ctf_type_t *)(fp->ctf_buf + hp->cth_typeoff);
202*7c478bd9Sstevel@tonic-gate 	/* LINTED - pointer alignment */
203*7c478bd9Sstevel@tonic-gate 	const ctf_type_t *tend = (ctf_type_t *)(fp->ctf_buf + hp->cth_stroff);
204*7c478bd9Sstevel@tonic-gate 
205*7c478bd9Sstevel@tonic-gate 	ulong_t pop[CTF_K_MAX + 1] = { 0 };
206*7c478bd9Sstevel@tonic-gate 	const ctf_type_t *tp;
207*7c478bd9Sstevel@tonic-gate 	ushort_t id, dst;
208*7c478bd9Sstevel@tonic-gate 	uint_t *xp;
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate 	/*
211*7c478bd9Sstevel@tonic-gate 	 * We initially determine whether the container is a child or a parent
212*7c478bd9Sstevel@tonic-gate 	 * based on the value of cth_parname.  To support containers that pre-
213*7c478bd9Sstevel@tonic-gate 	 * date cth_parname, we also scan the types themselves for references
214*7c478bd9Sstevel@tonic-gate 	 * to values in the range reserved for child types in our first pass.
215*7c478bd9Sstevel@tonic-gate 	 */
216*7c478bd9Sstevel@tonic-gate 	int child = hp->cth_parname != 0;
217*7c478bd9Sstevel@tonic-gate 	int nlstructs = 0, nlunions = 0;
218*7c478bd9Sstevel@tonic-gate 	int err;
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate 	/*
221*7c478bd9Sstevel@tonic-gate 	 * We make two passes through the entire type section.  In this first
222*7c478bd9Sstevel@tonic-gate 	 * pass, we count the number of each type and the total number of types.
223*7c478bd9Sstevel@tonic-gate 	 */
224*7c478bd9Sstevel@tonic-gate 	for (tp = tbuf; tp < tend; fp->ctf_typemax++) {
225*7c478bd9Sstevel@tonic-gate 		ushort_t kind = LCTF_INFO_KIND(fp, tp->ctt_info);
226*7c478bd9Sstevel@tonic-gate 		ulong_t vlen = LCTF_INFO_VLEN(fp, tp->ctt_info);
227*7c478bd9Sstevel@tonic-gate 		ssize_t size, increment;
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate 		size_t vbytes;
230*7c478bd9Sstevel@tonic-gate 		uint_t n;
231*7c478bd9Sstevel@tonic-gate 
232*7c478bd9Sstevel@tonic-gate 		(void) ctf_get_ctt_size(fp, tp, &size, &increment);
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate 		switch (kind) {
235*7c478bd9Sstevel@tonic-gate 		case CTF_K_INTEGER:
236*7c478bd9Sstevel@tonic-gate 		case CTF_K_FLOAT:
237*7c478bd9Sstevel@tonic-gate 			vbytes = sizeof (uint_t);
238*7c478bd9Sstevel@tonic-gate 			break;
239*7c478bd9Sstevel@tonic-gate 		case CTF_K_ARRAY:
240*7c478bd9Sstevel@tonic-gate 			vbytes = sizeof (ctf_array_t);
241*7c478bd9Sstevel@tonic-gate 			break;
242*7c478bd9Sstevel@tonic-gate 		case CTF_K_FUNCTION:
243*7c478bd9Sstevel@tonic-gate 			vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
244*7c478bd9Sstevel@tonic-gate 			break;
245*7c478bd9Sstevel@tonic-gate 		case CTF_K_STRUCT:
246*7c478bd9Sstevel@tonic-gate 		case CTF_K_UNION:
247*7c478bd9Sstevel@tonic-gate 			if (fp->ctf_version == CTF_VERSION_1 ||
248*7c478bd9Sstevel@tonic-gate 			    size < CTF_LSTRUCT_THRESH) {
249*7c478bd9Sstevel@tonic-gate 				ctf_member_t *mp = (ctf_member_t *)
250*7c478bd9Sstevel@tonic-gate 				    ((uintptr_t)tp + increment);
251*7c478bd9Sstevel@tonic-gate 
252*7c478bd9Sstevel@tonic-gate 				vbytes = sizeof (ctf_member_t) * vlen;
253*7c478bd9Sstevel@tonic-gate 				for (n = vlen; n != 0; n--, mp++)
254*7c478bd9Sstevel@tonic-gate 					child |= CTF_TYPE_ISCHILD(mp->ctm_type);
255*7c478bd9Sstevel@tonic-gate 			} else {
256*7c478bd9Sstevel@tonic-gate 				ctf_lmember_t *lmp = (ctf_lmember_t *)
257*7c478bd9Sstevel@tonic-gate 				    ((uintptr_t)tp + increment);
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate 				vbytes = sizeof (ctf_lmember_t) * vlen;
260*7c478bd9Sstevel@tonic-gate 				for (n = vlen; n != 0; n--, lmp++)
261*7c478bd9Sstevel@tonic-gate 					child |=
262*7c478bd9Sstevel@tonic-gate 					    CTF_TYPE_ISCHILD(lmp->ctlm_type);
263*7c478bd9Sstevel@tonic-gate 			}
264*7c478bd9Sstevel@tonic-gate 			break;
265*7c478bd9Sstevel@tonic-gate 		case CTF_K_ENUM:
266*7c478bd9Sstevel@tonic-gate 			vbytes = sizeof (ctf_enum_t) * vlen;
267*7c478bd9Sstevel@tonic-gate 			break;
268*7c478bd9Sstevel@tonic-gate 		case CTF_K_FORWARD:
269*7c478bd9Sstevel@tonic-gate 		case CTF_K_UNKNOWN:
270*7c478bd9Sstevel@tonic-gate 			vbytes = 0;
271*7c478bd9Sstevel@tonic-gate 			break;
272*7c478bd9Sstevel@tonic-gate 		case CTF_K_POINTER:
273*7c478bd9Sstevel@tonic-gate 		case CTF_K_TYPEDEF:
274*7c478bd9Sstevel@tonic-gate 		case CTF_K_VOLATILE:
275*7c478bd9Sstevel@tonic-gate 		case CTF_K_CONST:
276*7c478bd9Sstevel@tonic-gate 		case CTF_K_RESTRICT:
277*7c478bd9Sstevel@tonic-gate 			child |= CTF_TYPE_ISCHILD(tp->ctt_type);
278*7c478bd9Sstevel@tonic-gate 			vbytes = 0;
279*7c478bd9Sstevel@tonic-gate 			break;
280*7c478bd9Sstevel@tonic-gate 		default:
281*7c478bd9Sstevel@tonic-gate 			ctf_dprintf("detected invalid CTF kind -- %u\n", kind);
282*7c478bd9Sstevel@tonic-gate 			return (ECTF_CORRUPT);
283*7c478bd9Sstevel@tonic-gate 		}
284*7c478bd9Sstevel@tonic-gate 		tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
285*7c478bd9Sstevel@tonic-gate 		pop[kind]++;
286*7c478bd9Sstevel@tonic-gate 	}
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate 	/*
289*7c478bd9Sstevel@tonic-gate 	 * If we detected a reference to a child type ID, then we know this
290*7c478bd9Sstevel@tonic-gate 	 * container is a child and may have a parent's types imported later.
291*7c478bd9Sstevel@tonic-gate 	 */
292*7c478bd9Sstevel@tonic-gate 	if (child) {
293*7c478bd9Sstevel@tonic-gate 		ctf_dprintf("CTF container %p is a child\n", (void *)fp);
294*7c478bd9Sstevel@tonic-gate 		fp->ctf_flags |= LCTF_CHILD;
295*7c478bd9Sstevel@tonic-gate 	} else
296*7c478bd9Sstevel@tonic-gate 		ctf_dprintf("CTF container %p is a parent\n", (void *)fp);
297*7c478bd9Sstevel@tonic-gate 
298*7c478bd9Sstevel@tonic-gate 	/*
299*7c478bd9Sstevel@tonic-gate 	 * Now that we've counted up the number of each type, we can allocate
300*7c478bd9Sstevel@tonic-gate 	 * the hash tables, type translation table, and pointer table.
301*7c478bd9Sstevel@tonic-gate 	 */
302*7c478bd9Sstevel@tonic-gate 	if ((err = ctf_hash_create(&fp->ctf_structs,
303*7c478bd9Sstevel@tonic-gate 	    pop[CTF_K_STRUCT] + pop[CTF_K_FORWARD])) != 0)
304*7c478bd9Sstevel@tonic-gate 		return (err);
305*7c478bd9Sstevel@tonic-gate 
306*7c478bd9Sstevel@tonic-gate 	if ((err = ctf_hash_create(&fp->ctf_unions, pop[CTF_K_UNION])) != 0)
307*7c478bd9Sstevel@tonic-gate 		return (err);
308*7c478bd9Sstevel@tonic-gate 
309*7c478bd9Sstevel@tonic-gate 	if ((err = ctf_hash_create(&fp->ctf_enums, pop[CTF_K_ENUM])) != 0)
310*7c478bd9Sstevel@tonic-gate 		return (err);
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate 	if ((err = ctf_hash_create(&fp->ctf_names,
313*7c478bd9Sstevel@tonic-gate 	    pop[CTF_K_INTEGER] + pop[CTF_K_FLOAT] + pop[CTF_K_FUNCTION] +
314*7c478bd9Sstevel@tonic-gate 	    pop[CTF_K_TYPEDEF] + pop[CTF_K_POINTER] + pop[CTF_K_VOLATILE] +
315*7c478bd9Sstevel@tonic-gate 	    pop[CTF_K_CONST] + pop[CTF_K_RESTRICT])) != 0)
316*7c478bd9Sstevel@tonic-gate 		return (err);
317*7c478bd9Sstevel@tonic-gate 
318*7c478bd9Sstevel@tonic-gate 	fp->ctf_txlate = ctf_alloc(sizeof (uint_t) * (fp->ctf_typemax + 1));
319*7c478bd9Sstevel@tonic-gate 	fp->ctf_ptrtab = ctf_alloc(sizeof (ushort_t) * (fp->ctf_typemax + 1));
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate 	if (fp->ctf_txlate == NULL || fp->ctf_ptrtab == NULL)
322*7c478bd9Sstevel@tonic-gate 		return (EAGAIN); /* memory allocation failed */
323*7c478bd9Sstevel@tonic-gate 
324*7c478bd9Sstevel@tonic-gate 	xp = fp->ctf_txlate;
325*7c478bd9Sstevel@tonic-gate 	*xp++ = 0; /* type id 0 is used as a sentinel value */
326*7c478bd9Sstevel@tonic-gate 
327*7c478bd9Sstevel@tonic-gate 	bzero(fp->ctf_txlate, sizeof (uint_t) * (fp->ctf_typemax + 1));
328*7c478bd9Sstevel@tonic-gate 	bzero(fp->ctf_ptrtab, sizeof (ushort_t) * (fp->ctf_typemax + 1));
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate 	/*
331*7c478bd9Sstevel@tonic-gate 	 * In the second pass through the types, we fill in each entry of the
332*7c478bd9Sstevel@tonic-gate 	 * type and pointer tables and add names to the appropriate hashes.
333*7c478bd9Sstevel@tonic-gate 	 */
334*7c478bd9Sstevel@tonic-gate 	for (id = 1, tp = tbuf; tp < tend; xp++, id++) {
335*7c478bd9Sstevel@tonic-gate 		ushort_t kind = LCTF_INFO_KIND(fp, tp->ctt_info);
336*7c478bd9Sstevel@tonic-gate 		ulong_t vlen = LCTF_INFO_VLEN(fp, tp->ctt_info);
337*7c478bd9Sstevel@tonic-gate 		ssize_t size, increment;
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate 		const char *name;
340*7c478bd9Sstevel@tonic-gate 		size_t vbytes;
341*7c478bd9Sstevel@tonic-gate 		ctf_helem_t *hep;
342*7c478bd9Sstevel@tonic-gate 		ctf_encoding_t cte;
343*7c478bd9Sstevel@tonic-gate 
344*7c478bd9Sstevel@tonic-gate 		(void) ctf_get_ctt_size(fp, tp, &size, &increment);
345*7c478bd9Sstevel@tonic-gate 		name = ctf_strptr(fp, tp->ctt_name);
346*7c478bd9Sstevel@tonic-gate 
347*7c478bd9Sstevel@tonic-gate 		switch (kind) {
348*7c478bd9Sstevel@tonic-gate 		case CTF_K_INTEGER:
349*7c478bd9Sstevel@tonic-gate 		case CTF_K_FLOAT:
350*7c478bd9Sstevel@tonic-gate 			/*
351*7c478bd9Sstevel@tonic-gate 			 * Only insert a new integer base type definition if
352*7c478bd9Sstevel@tonic-gate 			 * this type name has not been defined yet.  We re-use
353*7c478bd9Sstevel@tonic-gate 			 * the names with different encodings for bit-fields.
354*7c478bd9Sstevel@tonic-gate 			 */
355*7c478bd9Sstevel@tonic-gate 			if ((hep = ctf_hash_lookup(&fp->ctf_names, fp,
356*7c478bd9Sstevel@tonic-gate 			    name, strlen(name))) == NULL) {
357*7c478bd9Sstevel@tonic-gate 				err = ctf_hash_insert(&fp->ctf_names, fp,
358*7c478bd9Sstevel@tonic-gate 				    CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);
359*7c478bd9Sstevel@tonic-gate 				if (err != 0 && err != ECTF_STRTAB)
360*7c478bd9Sstevel@tonic-gate 					return (err);
361*7c478bd9Sstevel@tonic-gate 			} else if (ctf_type_encoding(fp, hep->h_type,
362*7c478bd9Sstevel@tonic-gate 			    &cte) == 0 && cte.cte_bits == 0) {
363*7c478bd9Sstevel@tonic-gate 				/*
364*7c478bd9Sstevel@tonic-gate 				 * Work-around SOS8 stabs bug: replace existing
365*7c478bd9Sstevel@tonic-gate 				 * intrinsic w/ same name if it was zero bits.
366*7c478bd9Sstevel@tonic-gate 				 */
367*7c478bd9Sstevel@tonic-gate 				hep->h_type = CTF_INDEX_TO_TYPE(id, child);
368*7c478bd9Sstevel@tonic-gate 			}
369*7c478bd9Sstevel@tonic-gate 			vbytes = sizeof (uint_t);
370*7c478bd9Sstevel@tonic-gate 			break;
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate 		case CTF_K_ARRAY:
373*7c478bd9Sstevel@tonic-gate 			vbytes = sizeof (ctf_array_t);
374*7c478bd9Sstevel@tonic-gate 			break;
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate 		case CTF_K_FUNCTION:
377*7c478bd9Sstevel@tonic-gate 			err = ctf_hash_insert(&fp->ctf_names, fp,
378*7c478bd9Sstevel@tonic-gate 			    CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);
379*7c478bd9Sstevel@tonic-gate 			if (err != 0 && err != ECTF_STRTAB)
380*7c478bd9Sstevel@tonic-gate 				return (err);
381*7c478bd9Sstevel@tonic-gate 			vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
382*7c478bd9Sstevel@tonic-gate 			break;
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 		case CTF_K_STRUCT:
385*7c478bd9Sstevel@tonic-gate 			/*
386*7c478bd9Sstevel@tonic-gate 			 * If a struct's name is already present as a forward
387*7c478bd9Sstevel@tonic-gate 			 * tag, then replace the tag with the struct definition.
388*7c478bd9Sstevel@tonic-gate 			 */
389*7c478bd9Sstevel@tonic-gate 			if ((hep = ctf_hash_lookup(&fp->ctf_structs, fp,
390*7c478bd9Sstevel@tonic-gate 			    name, strlen(name))) == NULL) {
391*7c478bd9Sstevel@tonic-gate 				err = ctf_hash_insert(&fp->ctf_structs, fp,
392*7c478bd9Sstevel@tonic-gate 				    CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);
393*7c478bd9Sstevel@tonic-gate 				if (err != 0 && err != ECTF_STRTAB)
394*7c478bd9Sstevel@tonic-gate 					return (err);
395*7c478bd9Sstevel@tonic-gate 			} else
396*7c478bd9Sstevel@tonic-gate 				hep->h_type = CTF_INDEX_TO_TYPE(id, child);
397*7c478bd9Sstevel@tonic-gate 
398*7c478bd9Sstevel@tonic-gate 			if (fp->ctf_version == CTF_VERSION_1 ||
399*7c478bd9Sstevel@tonic-gate 			    size < CTF_LSTRUCT_THRESH)
400*7c478bd9Sstevel@tonic-gate 				vbytes = sizeof (ctf_member_t) * vlen;
401*7c478bd9Sstevel@tonic-gate 			else {
402*7c478bd9Sstevel@tonic-gate 				vbytes = sizeof (ctf_lmember_t) * vlen;
403*7c478bd9Sstevel@tonic-gate 				nlstructs++;
404*7c478bd9Sstevel@tonic-gate 			}
405*7c478bd9Sstevel@tonic-gate 			break;
406*7c478bd9Sstevel@tonic-gate 
407*7c478bd9Sstevel@tonic-gate 		case CTF_K_UNION:
408*7c478bd9Sstevel@tonic-gate 			err = ctf_hash_insert(&fp->ctf_unions, fp,
409*7c478bd9Sstevel@tonic-gate 			    CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);
410*7c478bd9Sstevel@tonic-gate 			if (err != 0 && err != ECTF_STRTAB)
411*7c478bd9Sstevel@tonic-gate 				return (err);
412*7c478bd9Sstevel@tonic-gate 
413*7c478bd9Sstevel@tonic-gate 			if (fp->ctf_version == CTF_VERSION_1 ||
414*7c478bd9Sstevel@tonic-gate 			    size < CTF_LSTRUCT_THRESH)
415*7c478bd9Sstevel@tonic-gate 				vbytes = sizeof (ctf_member_t) * vlen;
416*7c478bd9Sstevel@tonic-gate 			else {
417*7c478bd9Sstevel@tonic-gate 				vbytes = sizeof (ctf_lmember_t) * vlen;
418*7c478bd9Sstevel@tonic-gate 				nlunions++;
419*7c478bd9Sstevel@tonic-gate 			}
420*7c478bd9Sstevel@tonic-gate 			break;
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate 		case CTF_K_ENUM:
423*7c478bd9Sstevel@tonic-gate 			err = ctf_hash_insert(&fp->ctf_enums, fp,
424*7c478bd9Sstevel@tonic-gate 			    CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);
425*7c478bd9Sstevel@tonic-gate 			if (err != 0 && err != ECTF_STRTAB)
426*7c478bd9Sstevel@tonic-gate 				return (err);
427*7c478bd9Sstevel@tonic-gate 			vbytes = sizeof (ctf_enum_t) * vlen;
428*7c478bd9Sstevel@tonic-gate 			break;
429*7c478bd9Sstevel@tonic-gate 
430*7c478bd9Sstevel@tonic-gate 		case CTF_K_TYPEDEF:
431*7c478bd9Sstevel@tonic-gate 			err = ctf_hash_insert(&fp->ctf_names, fp,
432*7c478bd9Sstevel@tonic-gate 			    CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);
433*7c478bd9Sstevel@tonic-gate 			if (err != 0 && err != ECTF_STRTAB)
434*7c478bd9Sstevel@tonic-gate 				return (err);
435*7c478bd9Sstevel@tonic-gate 			vbytes = 0;
436*7c478bd9Sstevel@tonic-gate 			break;
437*7c478bd9Sstevel@tonic-gate 
438*7c478bd9Sstevel@tonic-gate 		case CTF_K_FORWARD:
439*7c478bd9Sstevel@tonic-gate 			/*
440*7c478bd9Sstevel@tonic-gate 			 * Only insert forward tags into the struct hash if the
441*7c478bd9Sstevel@tonic-gate 			 * struct or tag name is not already present.
442*7c478bd9Sstevel@tonic-gate 			 */
443*7c478bd9Sstevel@tonic-gate 			if (ctf_hash_lookup(&fp->ctf_structs, fp,
444*7c478bd9Sstevel@tonic-gate 			    name, strlen(name)) == NULL) {
445*7c478bd9Sstevel@tonic-gate 				err = ctf_hash_insert(&fp->ctf_structs, fp,
446*7c478bd9Sstevel@tonic-gate 				    CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);
447*7c478bd9Sstevel@tonic-gate 				if (err != 0 && err != ECTF_STRTAB)
448*7c478bd9Sstevel@tonic-gate 					return (err);
449*7c478bd9Sstevel@tonic-gate 			}
450*7c478bd9Sstevel@tonic-gate 			vbytes = 0;
451*7c478bd9Sstevel@tonic-gate 			break;
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate 		case CTF_K_POINTER:
454*7c478bd9Sstevel@tonic-gate 			/*
455*7c478bd9Sstevel@tonic-gate 			 * If the type referenced by the pointer is in this CTF
456*7c478bd9Sstevel@tonic-gate 			 * container, then store the index of the pointer type
457*7c478bd9Sstevel@tonic-gate 			 * in fp->ctf_ptrtab[ index of referenced type ].
458*7c478bd9Sstevel@tonic-gate 			 */
459*7c478bd9Sstevel@tonic-gate 			if (CTF_TYPE_ISCHILD(tp->ctt_type) == child &&
460*7c478bd9Sstevel@tonic-gate 			    CTF_TYPE_TO_INDEX(tp->ctt_type) <= fp->ctf_typemax)
461*7c478bd9Sstevel@tonic-gate 				fp->ctf_ptrtab[
462*7c478bd9Sstevel@tonic-gate 				    CTF_TYPE_TO_INDEX(tp->ctt_type)] = id;
463*7c478bd9Sstevel@tonic-gate 			/*FALLTHRU*/
464*7c478bd9Sstevel@tonic-gate 
465*7c478bd9Sstevel@tonic-gate 		case CTF_K_VOLATILE:
466*7c478bd9Sstevel@tonic-gate 		case CTF_K_CONST:
467*7c478bd9Sstevel@tonic-gate 		case CTF_K_RESTRICT:
468*7c478bd9Sstevel@tonic-gate 			err = ctf_hash_insert(&fp->ctf_names, fp,
469*7c478bd9Sstevel@tonic-gate 			    CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);
470*7c478bd9Sstevel@tonic-gate 			if (err != 0 && err != ECTF_STRTAB)
471*7c478bd9Sstevel@tonic-gate 				return (err);
472*7c478bd9Sstevel@tonic-gate 			/*FALLTHRU*/
473*7c478bd9Sstevel@tonic-gate 
474*7c478bd9Sstevel@tonic-gate 		default:
475*7c478bd9Sstevel@tonic-gate 			vbytes = 0;
476*7c478bd9Sstevel@tonic-gate 			break;
477*7c478bd9Sstevel@tonic-gate 		}
478*7c478bd9Sstevel@tonic-gate 
479*7c478bd9Sstevel@tonic-gate 		*xp = (uint_t)((uintptr_t)tp - (uintptr_t)fp->ctf_buf);
480*7c478bd9Sstevel@tonic-gate 		tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
481*7c478bd9Sstevel@tonic-gate 	}
482*7c478bd9Sstevel@tonic-gate 
483*7c478bd9Sstevel@tonic-gate 	ctf_dprintf("%lu total types processed\n", fp->ctf_typemax);
484*7c478bd9Sstevel@tonic-gate 	ctf_dprintf("%u enum names hashed\n", ctf_hash_size(&fp->ctf_enums));
485*7c478bd9Sstevel@tonic-gate 	ctf_dprintf("%u struct names hashed (%d long)\n",
486*7c478bd9Sstevel@tonic-gate 	    ctf_hash_size(&fp->ctf_structs), nlstructs);
487*7c478bd9Sstevel@tonic-gate 	ctf_dprintf("%u union names hashed (%d long)\n",
488*7c478bd9Sstevel@tonic-gate 	    ctf_hash_size(&fp->ctf_unions), nlunions);
489*7c478bd9Sstevel@tonic-gate 	ctf_dprintf("%u base type names hashed\n",
490*7c478bd9Sstevel@tonic-gate 	    ctf_hash_size(&fp->ctf_names));
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate 	/*
493*7c478bd9Sstevel@tonic-gate 	 * Make an additional pass through the pointer table to find pointers
494*7c478bd9Sstevel@tonic-gate 	 * that point to anonymous typedef nodes.  If we find one, modify the
495*7c478bd9Sstevel@tonic-gate 	 * pointer table so that the pointer is also known to point to the
496*7c478bd9Sstevel@tonic-gate 	 * node that is referenced by the anonymous typedef node.
497*7c478bd9Sstevel@tonic-gate 	 */
498*7c478bd9Sstevel@tonic-gate 	for (id = 1; id <= fp->ctf_typemax; id++) {
499*7c478bd9Sstevel@tonic-gate 		if ((dst = fp->ctf_ptrtab[id]) != 0) {
500*7c478bd9Sstevel@tonic-gate 			tp = LCTF_INDEX_TO_TYPEPTR(fp, id);
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate 			if (LCTF_INFO_KIND(fp, tp->ctt_info) == CTF_K_TYPEDEF &&
503*7c478bd9Sstevel@tonic-gate 			    strcmp(ctf_strptr(fp, tp->ctt_name), "") == 0 &&
504*7c478bd9Sstevel@tonic-gate 			    CTF_TYPE_ISCHILD(tp->ctt_type) == child &&
505*7c478bd9Sstevel@tonic-gate 			    CTF_TYPE_TO_INDEX(tp->ctt_type) <= fp->ctf_typemax)
506*7c478bd9Sstevel@tonic-gate 				fp->ctf_ptrtab[
507*7c478bd9Sstevel@tonic-gate 				    CTF_TYPE_TO_INDEX(tp->ctt_type)] = dst;
508*7c478bd9Sstevel@tonic-gate 		}
509*7c478bd9Sstevel@tonic-gate 	}
510*7c478bd9Sstevel@tonic-gate 
511*7c478bd9Sstevel@tonic-gate 	return (0);
512*7c478bd9Sstevel@tonic-gate }
513*7c478bd9Sstevel@tonic-gate 
514*7c478bd9Sstevel@tonic-gate /*
515*7c478bd9Sstevel@tonic-gate  * Decode the specified CTF buffer and optional symbol table and create a new
516*7c478bd9Sstevel@tonic-gate  * CTF container representing the symbolic debugging information.  This code
517*7c478bd9Sstevel@tonic-gate  * can be used directly by the debugger, or it can be used as the engine for
518*7c478bd9Sstevel@tonic-gate  * ctf_fdopen() or ctf_open(), below.
519*7c478bd9Sstevel@tonic-gate  */
520*7c478bd9Sstevel@tonic-gate ctf_file_t *
521*7c478bd9Sstevel@tonic-gate ctf_bufopen(const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
522*7c478bd9Sstevel@tonic-gate     const ctf_sect_t *strsect, int *errp)
523*7c478bd9Sstevel@tonic-gate {
524*7c478bd9Sstevel@tonic-gate 	const ctf_preamble_t *pp;
525*7c478bd9Sstevel@tonic-gate 	ctf_header_t hp;
526*7c478bd9Sstevel@tonic-gate 	ctf_file_t *fp;
527*7c478bd9Sstevel@tonic-gate 	void *buf, *base;
528*7c478bd9Sstevel@tonic-gate 	size_t size, hdrsz;
529*7c478bd9Sstevel@tonic-gate 	int err;
530*7c478bd9Sstevel@tonic-gate 
531*7c478bd9Sstevel@tonic-gate 	if (ctfsect == NULL || ((symsect == NULL) != (strsect == NULL)))
532*7c478bd9Sstevel@tonic-gate 		return (ctf_set_open_errno(errp, EINVAL));
533*7c478bd9Sstevel@tonic-gate 
534*7c478bd9Sstevel@tonic-gate 	if (symsect != NULL && symsect->cts_entsize != sizeof (Elf32_Sym) &&
535*7c478bd9Sstevel@tonic-gate 	    symsect->cts_entsize != sizeof (Elf64_Sym))
536*7c478bd9Sstevel@tonic-gate 		return (ctf_set_open_errno(errp, ECTF_SYMTAB));
537*7c478bd9Sstevel@tonic-gate 
538*7c478bd9Sstevel@tonic-gate 	if (symsect != NULL && symsect->cts_data == NULL)
539*7c478bd9Sstevel@tonic-gate 		return (ctf_set_open_errno(errp, ECTF_SYMBAD));
540*7c478bd9Sstevel@tonic-gate 
541*7c478bd9Sstevel@tonic-gate 	if (strsect != NULL && strsect->cts_data == NULL)
542*7c478bd9Sstevel@tonic-gate 		return (ctf_set_open_errno(errp, ECTF_STRBAD));
543*7c478bd9Sstevel@tonic-gate 
544*7c478bd9Sstevel@tonic-gate 	if (ctfsect->cts_size < sizeof (ctf_preamble_t))
545*7c478bd9Sstevel@tonic-gate 		return (ctf_set_open_errno(errp, ECTF_NOCTFBUF));
546*7c478bd9Sstevel@tonic-gate 
547*7c478bd9Sstevel@tonic-gate 	pp = (const ctf_preamble_t *)ctfsect->cts_data;
548*7c478bd9Sstevel@tonic-gate 
549*7c478bd9Sstevel@tonic-gate 	ctf_dprintf("ctf_bufopen: magic=0x%x version=%u\n",
550*7c478bd9Sstevel@tonic-gate 	    pp->ctp_magic, pp->ctp_version);
551*7c478bd9Sstevel@tonic-gate 
552*7c478bd9Sstevel@tonic-gate 	/*
553*7c478bd9Sstevel@tonic-gate 	 * Validate each part of the CTF header (either V1 or V2).
554*7c478bd9Sstevel@tonic-gate 	 * First, we validate the preamble (common to all versions).  At that
555*7c478bd9Sstevel@tonic-gate 	 * point, we know specific header version, and can validate the
556*7c478bd9Sstevel@tonic-gate 	 * version-specific parts including section offsets and alignments.
557*7c478bd9Sstevel@tonic-gate 	 */
558*7c478bd9Sstevel@tonic-gate 	if (pp->ctp_magic != CTF_MAGIC)
559*7c478bd9Sstevel@tonic-gate 		return (ctf_set_open_errno(errp, ECTF_NOCTFBUF));
560*7c478bd9Sstevel@tonic-gate 
561*7c478bd9Sstevel@tonic-gate 	if (pp->ctp_version == CTF_VERSION_2) {
562*7c478bd9Sstevel@tonic-gate 		if (ctfsect->cts_size < sizeof (ctf_header_t))
563*7c478bd9Sstevel@tonic-gate 			return (ctf_set_open_errno(errp, ECTF_NOCTFBUF));
564*7c478bd9Sstevel@tonic-gate 
565*7c478bd9Sstevel@tonic-gate 		bcopy(ctfsect->cts_data, &hp, sizeof (hp));
566*7c478bd9Sstevel@tonic-gate 		hdrsz = sizeof (ctf_header_t);
567*7c478bd9Sstevel@tonic-gate 
568*7c478bd9Sstevel@tonic-gate 	} else if (pp->ctp_version == CTF_VERSION_1) {
569*7c478bd9Sstevel@tonic-gate 		const ctf_header_v1_t *h1p =
570*7c478bd9Sstevel@tonic-gate 		    (const ctf_header_v1_t *)ctfsect->cts_data;
571*7c478bd9Sstevel@tonic-gate 
572*7c478bd9Sstevel@tonic-gate 		if (ctfsect->cts_size < sizeof (ctf_header_v1_t))
573*7c478bd9Sstevel@tonic-gate 			return (ctf_set_open_errno(errp, ECTF_NOCTFBUF));
574*7c478bd9Sstevel@tonic-gate 
575*7c478bd9Sstevel@tonic-gate 		bzero(&hp, sizeof (hp));
576*7c478bd9Sstevel@tonic-gate 		hp.cth_preamble = h1p->cth_preamble;
577*7c478bd9Sstevel@tonic-gate 		hp.cth_objtoff = h1p->cth_objtoff;
578*7c478bd9Sstevel@tonic-gate 		hp.cth_funcoff = h1p->cth_funcoff;
579*7c478bd9Sstevel@tonic-gate 		hp.cth_typeoff = h1p->cth_typeoff;
580*7c478bd9Sstevel@tonic-gate 		hp.cth_stroff = h1p->cth_stroff;
581*7c478bd9Sstevel@tonic-gate 		hp.cth_strlen = h1p->cth_strlen;
582*7c478bd9Sstevel@tonic-gate 
583*7c478bd9Sstevel@tonic-gate 		hdrsz = sizeof (ctf_header_v1_t);
584*7c478bd9Sstevel@tonic-gate 	} else
585*7c478bd9Sstevel@tonic-gate 		return (ctf_set_open_errno(errp, ECTF_CTFVERS));
586*7c478bd9Sstevel@tonic-gate 
587*7c478bd9Sstevel@tonic-gate 	size = hp.cth_stroff + hp.cth_strlen;
588*7c478bd9Sstevel@tonic-gate 
589*7c478bd9Sstevel@tonic-gate 	ctf_dprintf("ctf_bufopen: uncompressed size=%lu\n", (ulong_t)size);
590*7c478bd9Sstevel@tonic-gate 
591*7c478bd9Sstevel@tonic-gate 	if (hp.cth_lbloff > size || hp.cth_objtoff > size ||
592*7c478bd9Sstevel@tonic-gate 	    hp.cth_funcoff > size || hp.cth_typeoff > size ||
593*7c478bd9Sstevel@tonic-gate 	    hp.cth_stroff > size)
594*7c478bd9Sstevel@tonic-gate 		return (ctf_set_open_errno(errp, ECTF_CORRUPT));
595*7c478bd9Sstevel@tonic-gate 
596*7c478bd9Sstevel@tonic-gate 	if (hp.cth_lbloff > hp.cth_objtoff ||
597*7c478bd9Sstevel@tonic-gate 	    hp.cth_objtoff > hp.cth_funcoff ||
598*7c478bd9Sstevel@tonic-gate 	    hp.cth_funcoff > hp.cth_typeoff ||
599*7c478bd9Sstevel@tonic-gate 	    hp.cth_typeoff > hp.cth_stroff)
600*7c478bd9Sstevel@tonic-gate 		return (ctf_set_open_errno(errp, ECTF_CORRUPT));
601*7c478bd9Sstevel@tonic-gate 
602*7c478bd9Sstevel@tonic-gate 	if ((hp.cth_lbloff & 3) || (hp.cth_objtoff & 1) ||
603*7c478bd9Sstevel@tonic-gate 	    (hp.cth_funcoff & 1) || (hp.cth_typeoff & 3))
604*7c478bd9Sstevel@tonic-gate 		return (ctf_set_open_errno(errp, ECTF_CORRUPT));
605*7c478bd9Sstevel@tonic-gate 
606*7c478bd9Sstevel@tonic-gate 	/*
607*7c478bd9Sstevel@tonic-gate 	 * Once everything is determined to be valid, attempt to decompress
608*7c478bd9Sstevel@tonic-gate 	 * the CTF data buffer if it is compressed.  Otherwise we just put
609*7c478bd9Sstevel@tonic-gate 	 * the data section's buffer pointer into ctf_buf, below.
610*7c478bd9Sstevel@tonic-gate 	 */
611*7c478bd9Sstevel@tonic-gate 	if (hp.cth_flags & CTF_F_COMPRESS) {
612*7c478bd9Sstevel@tonic-gate 		size_t srclen, dstlen;
613*7c478bd9Sstevel@tonic-gate 		const void *src;
614*7c478bd9Sstevel@tonic-gate 		int rc = Z_OK;
615*7c478bd9Sstevel@tonic-gate 
616*7c478bd9Sstevel@tonic-gate 		if (ctf_zopen(errp) == NULL)
617*7c478bd9Sstevel@tonic-gate 			return (NULL); /* errp is set for us */
618*7c478bd9Sstevel@tonic-gate 
619*7c478bd9Sstevel@tonic-gate 		if ((base = ctf_data_alloc(size + hdrsz)) == MAP_FAILED)
620*7c478bd9Sstevel@tonic-gate 			return (ctf_set_open_errno(errp, ECTF_ZALLOC));
621*7c478bd9Sstevel@tonic-gate 
622*7c478bd9Sstevel@tonic-gate 		bcopy(ctfsect->cts_data, base, hdrsz);
623*7c478bd9Sstevel@tonic-gate 		((ctf_preamble_t *)base)->ctp_flags &= ~CTF_F_COMPRESS;
624*7c478bd9Sstevel@tonic-gate 		buf = (uchar_t *)base + hdrsz;
625*7c478bd9Sstevel@tonic-gate 
626*7c478bd9Sstevel@tonic-gate 		src = (uchar_t *)ctfsect->cts_data + hdrsz;
627*7c478bd9Sstevel@tonic-gate 		srclen = ctfsect->cts_size - hdrsz;
628*7c478bd9Sstevel@tonic-gate 		dstlen = size;
629*7c478bd9Sstevel@tonic-gate 
630*7c478bd9Sstevel@tonic-gate 		if ((rc = z_uncompress(buf, &dstlen, src, srclen)) != Z_OK) {
631*7c478bd9Sstevel@tonic-gate 			ctf_dprintf("zlib inflate err: %s\n", z_strerror(rc));
632*7c478bd9Sstevel@tonic-gate 			ctf_data_free(base, size + hdrsz);
633*7c478bd9Sstevel@tonic-gate 			return (ctf_set_open_errno(errp, ECTF_DECOMPRESS));
634*7c478bd9Sstevel@tonic-gate 		}
635*7c478bd9Sstevel@tonic-gate 
636*7c478bd9Sstevel@tonic-gate 		if (dstlen != size) {
637*7c478bd9Sstevel@tonic-gate 			ctf_dprintf("zlib inflate short -- got %lu of %lu "
638*7c478bd9Sstevel@tonic-gate 			    "bytes\n", (ulong_t)dstlen, (ulong_t)size);
639*7c478bd9Sstevel@tonic-gate 			ctf_data_free(base, size + hdrsz);
640*7c478bd9Sstevel@tonic-gate 			return (ctf_set_open_errno(errp, ECTF_CORRUPT));
641*7c478bd9Sstevel@tonic-gate 		}
642*7c478bd9Sstevel@tonic-gate 
643*7c478bd9Sstevel@tonic-gate 		ctf_data_protect(base, size + hdrsz);
644*7c478bd9Sstevel@tonic-gate 
645*7c478bd9Sstevel@tonic-gate 	} else {
646*7c478bd9Sstevel@tonic-gate 		base = (void *)ctfsect->cts_data;
647*7c478bd9Sstevel@tonic-gate 		buf = (uchar_t *)base + hdrsz;
648*7c478bd9Sstevel@tonic-gate 	}
649*7c478bd9Sstevel@tonic-gate 
650*7c478bd9Sstevel@tonic-gate 	/*
651*7c478bd9Sstevel@tonic-gate 	 * Once we have uncompressed and validated the CTF data buffer, we can
652*7c478bd9Sstevel@tonic-gate 	 * proceed with allocating a ctf_file_t and initializing it.
653*7c478bd9Sstevel@tonic-gate 	 */
654*7c478bd9Sstevel@tonic-gate 	if ((fp = ctf_alloc(sizeof (ctf_file_t))) == NULL)
655*7c478bd9Sstevel@tonic-gate 		return (ctf_set_open_errno(errp, EAGAIN));
656*7c478bd9Sstevel@tonic-gate 
657*7c478bd9Sstevel@tonic-gate 	bzero(fp, sizeof (ctf_file_t));
658*7c478bd9Sstevel@tonic-gate 	fp->ctf_version = hp.cth_version;
659*7c478bd9Sstevel@tonic-gate 	fp->ctf_fileops = &ctf_fileops[hp.cth_version];
660*7c478bd9Sstevel@tonic-gate 	bcopy(ctfsect, &fp->ctf_data, sizeof (ctf_sect_t));
661*7c478bd9Sstevel@tonic-gate 
662*7c478bd9Sstevel@tonic-gate 	if (symsect != NULL) {
663*7c478bd9Sstevel@tonic-gate 		bcopy(symsect, &fp->ctf_symtab, sizeof (ctf_sect_t));
664*7c478bd9Sstevel@tonic-gate 		bcopy(strsect, &fp->ctf_strtab, sizeof (ctf_sect_t));
665*7c478bd9Sstevel@tonic-gate 	}
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate 	if (fp->ctf_data.cts_name != NULL)
668*7c478bd9Sstevel@tonic-gate 		fp->ctf_data.cts_name = ctf_strdup(fp->ctf_data.cts_name);
669*7c478bd9Sstevel@tonic-gate 	if (fp->ctf_symtab.cts_name != NULL)
670*7c478bd9Sstevel@tonic-gate 		fp->ctf_symtab.cts_name = ctf_strdup(fp->ctf_symtab.cts_name);
671*7c478bd9Sstevel@tonic-gate 	if (fp->ctf_strtab.cts_name != NULL)
672*7c478bd9Sstevel@tonic-gate 		fp->ctf_strtab.cts_name = ctf_strdup(fp->ctf_strtab.cts_name);
673*7c478bd9Sstevel@tonic-gate 
674*7c478bd9Sstevel@tonic-gate 	if (fp->ctf_data.cts_name == NULL)
675*7c478bd9Sstevel@tonic-gate 		fp->ctf_data.cts_name = _CTF_NULLSTR;
676*7c478bd9Sstevel@tonic-gate 	if (fp->ctf_symtab.cts_name == NULL)
677*7c478bd9Sstevel@tonic-gate 		fp->ctf_symtab.cts_name = _CTF_NULLSTR;
678*7c478bd9Sstevel@tonic-gate 	if (fp->ctf_strtab.cts_name == NULL)
679*7c478bd9Sstevel@tonic-gate 		fp->ctf_strtab.cts_name = _CTF_NULLSTR;
680*7c478bd9Sstevel@tonic-gate 
681*7c478bd9Sstevel@tonic-gate 	fp->ctf_str[CTF_STRTAB_0].cts_strs = (const char *)buf + hp.cth_stroff;
682*7c478bd9Sstevel@tonic-gate 	fp->ctf_str[CTF_STRTAB_0].cts_len = hp.cth_strlen;
683*7c478bd9Sstevel@tonic-gate 
684*7c478bd9Sstevel@tonic-gate 	if (strsect != NULL) {
685*7c478bd9Sstevel@tonic-gate 		fp->ctf_str[CTF_STRTAB_1].cts_strs = strsect->cts_data;
686*7c478bd9Sstevel@tonic-gate 		fp->ctf_str[CTF_STRTAB_1].cts_len = strsect->cts_size;
687*7c478bd9Sstevel@tonic-gate 	}
688*7c478bd9Sstevel@tonic-gate 
689*7c478bd9Sstevel@tonic-gate 	fp->ctf_base = base;
690*7c478bd9Sstevel@tonic-gate 	fp->ctf_buf = buf;
691*7c478bd9Sstevel@tonic-gate 	fp->ctf_size = size + hdrsz;
692*7c478bd9Sstevel@tonic-gate 
693*7c478bd9Sstevel@tonic-gate 	/*
694*7c478bd9Sstevel@tonic-gate 	 * If we have a parent container name and label, store the relocated
695*7c478bd9Sstevel@tonic-gate 	 * string pointers in the CTF container for easy access later.
696*7c478bd9Sstevel@tonic-gate 	 */
697*7c478bd9Sstevel@tonic-gate 	if (hp.cth_parlabel != 0)
698*7c478bd9Sstevel@tonic-gate 		fp->ctf_parlabel = ctf_strptr(fp, hp.cth_parlabel);
699*7c478bd9Sstevel@tonic-gate 	if (hp.cth_parname != 0)
700*7c478bd9Sstevel@tonic-gate 		fp->ctf_parname = ctf_strptr(fp, hp.cth_parname);
701*7c478bd9Sstevel@tonic-gate 
702*7c478bd9Sstevel@tonic-gate 	ctf_dprintf("ctf_bufopen: parent name %s (label %s)\n",
703*7c478bd9Sstevel@tonic-gate 	    fp->ctf_parname ? fp->ctf_parname : "<NULL>",
704*7c478bd9Sstevel@tonic-gate 	    fp->ctf_parlabel ? fp->ctf_parlabel : "<NULL>");
705*7c478bd9Sstevel@tonic-gate 
706*7c478bd9Sstevel@tonic-gate 	/*
707*7c478bd9Sstevel@tonic-gate 	 * If we have a symbol table section, allocate and initialize
708*7c478bd9Sstevel@tonic-gate 	 * the symtab translation table, pointed to by ctf_sxlate.
709*7c478bd9Sstevel@tonic-gate 	 */
710*7c478bd9Sstevel@tonic-gate 	if (symsect != NULL) {
711*7c478bd9Sstevel@tonic-gate 		fp->ctf_nsyms = symsect->cts_size / symsect->cts_entsize;
712*7c478bd9Sstevel@tonic-gate 		fp->ctf_sxlate = ctf_alloc(fp->ctf_nsyms * sizeof (uint_t));
713*7c478bd9Sstevel@tonic-gate 
714*7c478bd9Sstevel@tonic-gate 		if (fp->ctf_sxlate == NULL) {
715*7c478bd9Sstevel@tonic-gate 			(void) ctf_set_open_errno(errp, EAGAIN);
716*7c478bd9Sstevel@tonic-gate 			goto bad;
717*7c478bd9Sstevel@tonic-gate 		}
718*7c478bd9Sstevel@tonic-gate 
719*7c478bd9Sstevel@tonic-gate 		if ((err = init_symtab(fp, &hp, symsect, strsect)) != 0) {
720*7c478bd9Sstevel@tonic-gate 			(void) ctf_set_open_errno(errp, err);
721*7c478bd9Sstevel@tonic-gate 			goto bad;
722*7c478bd9Sstevel@tonic-gate 		}
723*7c478bd9Sstevel@tonic-gate 	}
724*7c478bd9Sstevel@tonic-gate 
725*7c478bd9Sstevel@tonic-gate 	if ((err = init_types(fp, &hp)) != 0) {
726*7c478bd9Sstevel@tonic-gate 		(void) ctf_set_open_errno(errp, err);
727*7c478bd9Sstevel@tonic-gate 		goto bad;
728*7c478bd9Sstevel@tonic-gate 	}
729*7c478bd9Sstevel@tonic-gate 
730*7c478bd9Sstevel@tonic-gate 	/*
731*7c478bd9Sstevel@tonic-gate 	 * Initialize the ctf_lookup_by_name top-level dictionary.  We keep an
732*7c478bd9Sstevel@tonic-gate 	 * array of type name prefixes and the corresponding ctf_hash to use.
733*7c478bd9Sstevel@tonic-gate 	 * NOTE: This code must be kept in sync with the code in ctf_update().
734*7c478bd9Sstevel@tonic-gate 	 */
735*7c478bd9Sstevel@tonic-gate 	fp->ctf_lookups[0].ctl_prefix = "struct";
736*7c478bd9Sstevel@tonic-gate 	fp->ctf_lookups[0].ctl_len = strlen(fp->ctf_lookups[0].ctl_prefix);
737*7c478bd9Sstevel@tonic-gate 	fp->ctf_lookups[0].ctl_hash = &fp->ctf_structs;
738*7c478bd9Sstevel@tonic-gate 	fp->ctf_lookups[1].ctl_prefix = "union";
739*7c478bd9Sstevel@tonic-gate 	fp->ctf_lookups[1].ctl_len = strlen(fp->ctf_lookups[1].ctl_prefix);
740*7c478bd9Sstevel@tonic-gate 	fp->ctf_lookups[1].ctl_hash = &fp->ctf_unions;
741*7c478bd9Sstevel@tonic-gate 	fp->ctf_lookups[2].ctl_prefix = "enum";
742*7c478bd9Sstevel@tonic-gate 	fp->ctf_lookups[2].ctl_len = strlen(fp->ctf_lookups[2].ctl_prefix);
743*7c478bd9Sstevel@tonic-gate 	fp->ctf_lookups[2].ctl_hash = &fp->ctf_enums;
744*7c478bd9Sstevel@tonic-gate 	fp->ctf_lookups[3].ctl_prefix = _CTF_NULLSTR;
745*7c478bd9Sstevel@tonic-gate 	fp->ctf_lookups[3].ctl_len = strlen(fp->ctf_lookups[3].ctl_prefix);
746*7c478bd9Sstevel@tonic-gate 	fp->ctf_lookups[3].ctl_hash = &fp->ctf_names;
747*7c478bd9Sstevel@tonic-gate 	fp->ctf_lookups[4].ctl_prefix = NULL;
748*7c478bd9Sstevel@tonic-gate 	fp->ctf_lookups[4].ctl_len = 0;
749*7c478bd9Sstevel@tonic-gate 	fp->ctf_lookups[4].ctl_hash = NULL;
750*7c478bd9Sstevel@tonic-gate 
751*7c478bd9Sstevel@tonic-gate 	if (symsect != NULL) {
752*7c478bd9Sstevel@tonic-gate 		if (symsect->cts_entsize == sizeof (Elf64_Sym))
753*7c478bd9Sstevel@tonic-gate 			(void) ctf_setmodel(fp, CTF_MODEL_LP64);
754*7c478bd9Sstevel@tonic-gate 		else
755*7c478bd9Sstevel@tonic-gate 			(void) ctf_setmodel(fp, CTF_MODEL_ILP32);
756*7c478bd9Sstevel@tonic-gate 	} else
757*7c478bd9Sstevel@tonic-gate 		(void) ctf_setmodel(fp, CTF_MODEL_NATIVE);
758*7c478bd9Sstevel@tonic-gate 
759*7c478bd9Sstevel@tonic-gate 	fp->ctf_refcnt = 1;
760*7c478bd9Sstevel@tonic-gate 	return (fp);
761*7c478bd9Sstevel@tonic-gate 
762*7c478bd9Sstevel@tonic-gate bad:
763*7c478bd9Sstevel@tonic-gate 	ctf_close(fp);
764*7c478bd9Sstevel@tonic-gate 	return (NULL);
765*7c478bd9Sstevel@tonic-gate }
766*7c478bd9Sstevel@tonic-gate 
767*7c478bd9Sstevel@tonic-gate /*
768*7c478bd9Sstevel@tonic-gate  * Close the specified CTF container and free associated data structures.  Note
769*7c478bd9Sstevel@tonic-gate  * that ctf_close() is a reference counted operation: if the specified file is
770*7c478bd9Sstevel@tonic-gate  * the parent of other active containers, its reference count will be greater
771*7c478bd9Sstevel@tonic-gate  * than one and it will be freed later when no active children exist.
772*7c478bd9Sstevel@tonic-gate  */
773*7c478bd9Sstevel@tonic-gate void
774*7c478bd9Sstevel@tonic-gate ctf_close(ctf_file_t *fp)
775*7c478bd9Sstevel@tonic-gate {
776*7c478bd9Sstevel@tonic-gate 	ctf_dtdef_t *dtd, *ntd;
777*7c478bd9Sstevel@tonic-gate 	ctf_dmdef_t *dmd, *nmd;
778*7c478bd9Sstevel@tonic-gate 
779*7c478bd9Sstevel@tonic-gate 	if (fp == NULL)
780*7c478bd9Sstevel@tonic-gate 		return; /* allow ctf_close(NULL) to simplify caller code */
781*7c478bd9Sstevel@tonic-gate 
782*7c478bd9Sstevel@tonic-gate 	ctf_dprintf("ctf_close(%p) refcnt=%u\n", (void *)fp, fp->ctf_refcnt);
783*7c478bd9Sstevel@tonic-gate 
784*7c478bd9Sstevel@tonic-gate 	if (fp->ctf_refcnt > 1) {
785*7c478bd9Sstevel@tonic-gate 		fp->ctf_refcnt--;
786*7c478bd9Sstevel@tonic-gate 		return;
787*7c478bd9Sstevel@tonic-gate 	}
788*7c478bd9Sstevel@tonic-gate 
789*7c478bd9Sstevel@tonic-gate 	for (dtd = ctf_list_next(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
790*7c478bd9Sstevel@tonic-gate 		switch (CTF_INFO_KIND(dtd->dtd_data.ctt_info)) {
791*7c478bd9Sstevel@tonic-gate 		case CTF_K_STRUCT:
792*7c478bd9Sstevel@tonic-gate 		case CTF_K_UNION:
793*7c478bd9Sstevel@tonic-gate 		case CTF_K_ENUM:
794*7c478bd9Sstevel@tonic-gate 			for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
795*7c478bd9Sstevel@tonic-gate 			    dmd != NULL; dmd = nmd) {
796*7c478bd9Sstevel@tonic-gate 				if (dmd->dmd_name != NULL) {
797*7c478bd9Sstevel@tonic-gate 					ctf_free(dmd->dmd_name,
798*7c478bd9Sstevel@tonic-gate 					    strlen(dmd->dmd_name) + 1);
799*7c478bd9Sstevel@tonic-gate 				}
800*7c478bd9Sstevel@tonic-gate 				nmd = ctf_list_next(dmd);
801*7c478bd9Sstevel@tonic-gate 				ctf_free(dmd, sizeof (ctf_dmdef_t));
802*7c478bd9Sstevel@tonic-gate 			}
803*7c478bd9Sstevel@tonic-gate 			break;
804*7c478bd9Sstevel@tonic-gate 		case CTF_K_FUNCTION:
805*7c478bd9Sstevel@tonic-gate 			ctf_free(dtd->dtd_u.dtu_argv, sizeof (ctf_id_t) *
806*7c478bd9Sstevel@tonic-gate 			    CTF_INFO_VLEN(dtd->dtd_data.ctt_info));
807*7c478bd9Sstevel@tonic-gate 			break;
808*7c478bd9Sstevel@tonic-gate 		}
809*7c478bd9Sstevel@tonic-gate 
810*7c478bd9Sstevel@tonic-gate 		if (dtd->dtd_name != NULL)
811*7c478bd9Sstevel@tonic-gate 			ctf_free(dtd->dtd_name, strlen(dtd->dtd_name) + 1);
812*7c478bd9Sstevel@tonic-gate 
813*7c478bd9Sstevel@tonic-gate 		ntd = ctf_list_next(dtd);
814*7c478bd9Sstevel@tonic-gate 		ctf_free(dtd, sizeof (ctf_dtdef_t));
815*7c478bd9Sstevel@tonic-gate 	}
816*7c478bd9Sstevel@tonic-gate 
817*7c478bd9Sstevel@tonic-gate 	if (fp->ctf_parent != NULL)
818*7c478bd9Sstevel@tonic-gate 		ctf_close(fp->ctf_parent);
819*7c478bd9Sstevel@tonic-gate 
820*7c478bd9Sstevel@tonic-gate 	if (fp->ctf_flags & LCTF_MMAP) {
821*7c478bd9Sstevel@tonic-gate 		if (fp->ctf_data.cts_data != NULL)
822*7c478bd9Sstevel@tonic-gate 			ctf_sect_munmap(&fp->ctf_data);
823*7c478bd9Sstevel@tonic-gate 		if (fp->ctf_symtab.cts_data != NULL)
824*7c478bd9Sstevel@tonic-gate 			ctf_sect_munmap(&fp->ctf_symtab);
825*7c478bd9Sstevel@tonic-gate 		if (fp->ctf_strtab.cts_data != NULL)
826*7c478bd9Sstevel@tonic-gate 			ctf_sect_munmap(&fp->ctf_strtab);
827*7c478bd9Sstevel@tonic-gate 	}
828*7c478bd9Sstevel@tonic-gate 
829*7c478bd9Sstevel@tonic-gate 	if (fp->ctf_data.cts_name != _CTF_NULLSTR &&
830*7c478bd9Sstevel@tonic-gate 	    fp->ctf_data.cts_name != NULL) {
831*7c478bd9Sstevel@tonic-gate 		ctf_free((char *)fp->ctf_data.cts_name,
832*7c478bd9Sstevel@tonic-gate 		    strlen(fp->ctf_data.cts_name) + 1);
833*7c478bd9Sstevel@tonic-gate 	}
834*7c478bd9Sstevel@tonic-gate 
835*7c478bd9Sstevel@tonic-gate 	if (fp->ctf_symtab.cts_name != _CTF_NULLSTR &&
836*7c478bd9Sstevel@tonic-gate 	    fp->ctf_symtab.cts_name != NULL) {
837*7c478bd9Sstevel@tonic-gate 		ctf_free((char *)fp->ctf_symtab.cts_name,
838*7c478bd9Sstevel@tonic-gate 		    strlen(fp->ctf_symtab.cts_name) + 1);
839*7c478bd9Sstevel@tonic-gate 	}
840*7c478bd9Sstevel@tonic-gate 
841*7c478bd9Sstevel@tonic-gate 	if (fp->ctf_strtab.cts_name != _CTF_NULLSTR &&
842*7c478bd9Sstevel@tonic-gate 	    fp->ctf_strtab.cts_name != NULL) {
843*7c478bd9Sstevel@tonic-gate 		ctf_free((char *)fp->ctf_strtab.cts_name,
844*7c478bd9Sstevel@tonic-gate 		    strlen(fp->ctf_strtab.cts_name) + 1);
845*7c478bd9Sstevel@tonic-gate 	}
846*7c478bd9Sstevel@tonic-gate 
847*7c478bd9Sstevel@tonic-gate 	if (fp->ctf_base != fp->ctf_data.cts_data && fp->ctf_base != NULL)
848*7c478bd9Sstevel@tonic-gate 		ctf_data_free((void *)fp->ctf_base, fp->ctf_size);
849*7c478bd9Sstevel@tonic-gate 
850*7c478bd9Sstevel@tonic-gate 	if (fp->ctf_sxlate != NULL)
851*7c478bd9Sstevel@tonic-gate 		ctf_free(fp->ctf_sxlate, sizeof (uint_t) * fp->ctf_nsyms);
852*7c478bd9Sstevel@tonic-gate 
853*7c478bd9Sstevel@tonic-gate 	if (fp->ctf_txlate != NULL) {
854*7c478bd9Sstevel@tonic-gate 		ctf_free(fp->ctf_txlate,
855*7c478bd9Sstevel@tonic-gate 		    sizeof (uint_t) * (fp->ctf_typemax + 1));
856*7c478bd9Sstevel@tonic-gate 	}
857*7c478bd9Sstevel@tonic-gate 
858*7c478bd9Sstevel@tonic-gate 	if (fp->ctf_ptrtab != NULL) {
859*7c478bd9Sstevel@tonic-gate 		ctf_free(fp->ctf_ptrtab,
860*7c478bd9Sstevel@tonic-gate 		    sizeof (ushort_t) * (fp->ctf_typemax + 1));
861*7c478bd9Sstevel@tonic-gate 	}
862*7c478bd9Sstevel@tonic-gate 
863*7c478bd9Sstevel@tonic-gate 	ctf_hash_destroy(&fp->ctf_structs);
864*7c478bd9Sstevel@tonic-gate 	ctf_hash_destroy(&fp->ctf_unions);
865*7c478bd9Sstevel@tonic-gate 	ctf_hash_destroy(&fp->ctf_enums);
866*7c478bd9Sstevel@tonic-gate 	ctf_hash_destroy(&fp->ctf_names);
867*7c478bd9Sstevel@tonic-gate 
868*7c478bd9Sstevel@tonic-gate 	ctf_free(fp, sizeof (ctf_file_t));
869*7c478bd9Sstevel@tonic-gate }
870*7c478bd9Sstevel@tonic-gate 
871*7c478bd9Sstevel@tonic-gate /*
872*7c478bd9Sstevel@tonic-gate  * Return the CTF handle for the parent CTF container, if one exists.
873*7c478bd9Sstevel@tonic-gate  * Otherwise return NULL to indicate this container has no imported parent.
874*7c478bd9Sstevel@tonic-gate  */
875*7c478bd9Sstevel@tonic-gate ctf_file_t *
876*7c478bd9Sstevel@tonic-gate ctf_parent_file(ctf_file_t *fp)
877*7c478bd9Sstevel@tonic-gate {
878*7c478bd9Sstevel@tonic-gate 	return (fp->ctf_parent);
879*7c478bd9Sstevel@tonic-gate }
880*7c478bd9Sstevel@tonic-gate 
881*7c478bd9Sstevel@tonic-gate /*
882*7c478bd9Sstevel@tonic-gate  * Return the name of the parent CTF container, if one exists.  Otherwise
883*7c478bd9Sstevel@tonic-gate  * return NULL to indicate this container is a root container.
884*7c478bd9Sstevel@tonic-gate  */
885*7c478bd9Sstevel@tonic-gate const char *
886*7c478bd9Sstevel@tonic-gate ctf_parent_name(ctf_file_t *fp)
887*7c478bd9Sstevel@tonic-gate {
888*7c478bd9Sstevel@tonic-gate 	return (fp->ctf_parname);
889*7c478bd9Sstevel@tonic-gate }
890*7c478bd9Sstevel@tonic-gate 
891*7c478bd9Sstevel@tonic-gate /*
892*7c478bd9Sstevel@tonic-gate  * Import the types from the specified parent container by storing a pointer
893*7c478bd9Sstevel@tonic-gate  * to it in ctf_parent and incrementing its reference count.  Only one parent
894*7c478bd9Sstevel@tonic-gate  * is allowed: if a parent already exists, it is replaced by the new parent.
895*7c478bd9Sstevel@tonic-gate  */
896*7c478bd9Sstevel@tonic-gate int
897*7c478bd9Sstevel@tonic-gate ctf_import(ctf_file_t *fp, ctf_file_t *pfp)
898*7c478bd9Sstevel@tonic-gate {
899*7c478bd9Sstevel@tonic-gate 	if (fp == NULL || fp == pfp || (pfp != NULL && pfp->ctf_refcnt == 0))
900*7c478bd9Sstevel@tonic-gate 		return (ctf_set_errno(fp, EINVAL));
901*7c478bd9Sstevel@tonic-gate 
902*7c478bd9Sstevel@tonic-gate 	if (pfp != NULL && pfp->ctf_dmodel != fp->ctf_dmodel)
903*7c478bd9Sstevel@tonic-gate 		return (ctf_set_errno(fp, ECTF_DMODEL));
904*7c478bd9Sstevel@tonic-gate 
905*7c478bd9Sstevel@tonic-gate 	if (fp->ctf_parent != NULL)
906*7c478bd9Sstevel@tonic-gate 		ctf_close(fp->ctf_parent);
907*7c478bd9Sstevel@tonic-gate 
908*7c478bd9Sstevel@tonic-gate 	if (pfp != NULL) {
909*7c478bd9Sstevel@tonic-gate 		fp->ctf_flags |= LCTF_CHILD;
910*7c478bd9Sstevel@tonic-gate 		pfp->ctf_refcnt++;
911*7c478bd9Sstevel@tonic-gate 	}
912*7c478bd9Sstevel@tonic-gate 
913*7c478bd9Sstevel@tonic-gate 	fp->ctf_parent = pfp;
914*7c478bd9Sstevel@tonic-gate 	return (0);
915*7c478bd9Sstevel@tonic-gate }
916*7c478bd9Sstevel@tonic-gate 
917*7c478bd9Sstevel@tonic-gate /*
918*7c478bd9Sstevel@tonic-gate  * Set the data model constant for the CTF container.
919*7c478bd9Sstevel@tonic-gate  */
920*7c478bd9Sstevel@tonic-gate int
921*7c478bd9Sstevel@tonic-gate ctf_setmodel(ctf_file_t *fp, int model)
922*7c478bd9Sstevel@tonic-gate {
923*7c478bd9Sstevel@tonic-gate 	const ctf_dmodel_t *dp;
924*7c478bd9Sstevel@tonic-gate 
925*7c478bd9Sstevel@tonic-gate 	for (dp = _libctf_models; dp->ctd_name != NULL; dp++) {
926*7c478bd9Sstevel@tonic-gate 		if (dp->ctd_code == model) {
927*7c478bd9Sstevel@tonic-gate 			fp->ctf_dmodel = dp;
928*7c478bd9Sstevel@tonic-gate 			return (0);
929*7c478bd9Sstevel@tonic-gate 		}
930*7c478bd9Sstevel@tonic-gate 	}
931*7c478bd9Sstevel@tonic-gate 
932*7c478bd9Sstevel@tonic-gate 	return (ctf_set_errno(fp, EINVAL));
933*7c478bd9Sstevel@tonic-gate }
934*7c478bd9Sstevel@tonic-gate 
935*7c478bd9Sstevel@tonic-gate /*
936*7c478bd9Sstevel@tonic-gate  * Return the data model constant for the CTF container.
937*7c478bd9Sstevel@tonic-gate  */
938*7c478bd9Sstevel@tonic-gate int
939*7c478bd9Sstevel@tonic-gate ctf_getmodel(ctf_file_t *fp)
940*7c478bd9Sstevel@tonic-gate {
941*7c478bd9Sstevel@tonic-gate 	return (fp->ctf_dmodel->ctd_code);
942*7c478bd9Sstevel@tonic-gate }
943*7c478bd9Sstevel@tonic-gate 
944*7c478bd9Sstevel@tonic-gate void
945*7c478bd9Sstevel@tonic-gate ctf_setspecific(ctf_file_t *fp, void *data)
946*7c478bd9Sstevel@tonic-gate {
947*7c478bd9Sstevel@tonic-gate 	fp->ctf_specific = data;
948*7c478bd9Sstevel@tonic-gate }
949*7c478bd9Sstevel@tonic-gate 
950*7c478bd9Sstevel@tonic-gate void *
951*7c478bd9Sstevel@tonic-gate ctf_getspecific(ctf_file_t *fp)
952*7c478bd9Sstevel@tonic-gate {
953*7c478bd9Sstevel@tonic-gate 	return (fp->ctf_specific);
954*7c478bd9Sstevel@tonic-gate }
955