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