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