1d876124dSJohn Birrell /*
2d876124dSJohn Birrell  * CDDL HEADER START
3d876124dSJohn Birrell  *
4d876124dSJohn Birrell  * The contents of this file are subject to the terms of the
5d876124dSJohn Birrell  * Common Development and Distribution License, Version 1.0 only
6d876124dSJohn Birrell  * (the "License").  You may not use this file except in compliance
7d876124dSJohn Birrell  * with the License.
8d876124dSJohn Birrell  *
9d876124dSJohn Birrell  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10d876124dSJohn Birrell  * or http://www.opensolaris.org/os/licensing.
11d876124dSJohn Birrell  * See the License for the specific language governing permissions
12d876124dSJohn Birrell  * and limitations under the License.
13d876124dSJohn Birrell  *
14d876124dSJohn Birrell  * When distributing Covered Code, include this CDDL HEADER in each
15d876124dSJohn Birrell  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16d876124dSJohn Birrell  * If applicable, add the following below this CDDL HEADER, with the
17d876124dSJohn Birrell  * fields enclosed by brackets "[]" replaced with your own identifying
18d876124dSJohn Birrell  * information: Portions Copyright [yyyy] [name of copyright owner]
19d876124dSJohn Birrell  *
20d876124dSJohn Birrell  * CDDL HEADER END
21d876124dSJohn Birrell  */
22d876124dSJohn Birrell 
23d876124dSJohn Birrell /*
24d876124dSJohn Birrell  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
25d876124dSJohn Birrell  * Use is subject to license terms.
26d876124dSJohn Birrell  */
273f0164abSXin LI /*
288e648814SRui Paulo  * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
293f0164abSXin LI  */
30d876124dSJohn Birrell 
31d876124dSJohn Birrell #include <ctf_impl.h>
32d876124dSJohn Birrell #include <sys/mman.h>
33d876124dSJohn Birrell #include <sys/zmod.h>
34d876124dSJohn Birrell 
35d876124dSJohn Birrell static const ctf_dmodel_t _libctf_models[] = {
36d876124dSJohn Birrell 	{ "ILP32", CTF_MODEL_ILP32, 4, 1, 2, 4, 4 },
37d876124dSJohn Birrell 	{ "LP64", CTF_MODEL_LP64, 8, 1, 2, 4, 8 },
38d876124dSJohn Birrell 	{ NULL, 0, 0, 0, 0, 0, 0 }
39d876124dSJohn Birrell };
40d876124dSJohn Birrell 
41d876124dSJohn Birrell const char _CTF_SECTION[] = ".SUNW_ctf";
42d876124dSJohn Birrell const char _CTF_NULLSTR[] = "";
43d876124dSJohn Birrell 
44d876124dSJohn Birrell int _libctf_version = CTF_VERSION;	/* library client version */
45d876124dSJohn Birrell int _libctf_debug = 0;			/* debugging messages enabled */
46d876124dSJohn Birrell 
47a6fb8691SMark Johnston static uint_t
get_kind_v2(uint_t info)48a6fb8691SMark Johnston get_kind_v2(uint_t info)
49d876124dSJohn Birrell {
50a6fb8691SMark Johnston 	return (CTF_V2_INFO_KIND((ushort_t)info));
51d876124dSJohn Birrell }
52d876124dSJohn Birrell 
53a6fb8691SMark Johnston static uint_t
get_root_v2(uint_t info)54a6fb8691SMark Johnston get_root_v2(uint_t info)
55d876124dSJohn Birrell {
56a6fb8691SMark Johnston 	return (CTF_V2_INFO_ISROOT((ushort_t)info));
57d876124dSJohn Birrell }
58d876124dSJohn Birrell 
59a6fb8691SMark Johnston static uint_t
get_vlen_v2(uint_t info)60a6fb8691SMark Johnston get_vlen_v2(uint_t info)
61d876124dSJohn Birrell {
62a6fb8691SMark Johnston 	return (CTF_V2_INFO_VLEN((ushort_t)info));
63a6fb8691SMark Johnston }
64a6fb8691SMark Johnston 
65a6fb8691SMark Johnston static uint_t
get_max_vlen_v2(void)66a6fb8691SMark Johnston get_max_vlen_v2(void)
67a6fb8691SMark Johnston {
68a6fb8691SMark Johnston 	return (CTF_V2_MAX_VLEN);
69a6fb8691SMark Johnston }
70a6fb8691SMark Johnston 
71a6fb8691SMark Johnston static uint_t
get_max_size_v2(void)72a6fb8691SMark Johnston get_max_size_v2(void)
73a6fb8691SMark Johnston {
74a6fb8691SMark Johnston 	return (CTF_V2_MAX_SIZE);
75a6fb8691SMark Johnston }
76a6fb8691SMark Johnston 
77a6fb8691SMark Johnston static uint_t
get_max_type_v2(void)78a6fb8691SMark Johnston get_max_type_v2(void)
79a6fb8691SMark Johnston {
80a6fb8691SMark Johnston 	return (CTF_V2_MAX_TYPE);
81a6fb8691SMark Johnston }
82a6fb8691SMark Johnston 
83a6fb8691SMark Johnston static uint_t
get_lsize_sent_v2(void)84a6fb8691SMark Johnston get_lsize_sent_v2(void)
85a6fb8691SMark Johnston {
86a6fb8691SMark Johnston 	return (CTF_V2_LSIZE_SENT);
87a6fb8691SMark Johnston }
88a6fb8691SMark Johnston 
89a6fb8691SMark Johnston static uint_t
get_lstruct_thresh_v2(void)90a6fb8691SMark Johnston get_lstruct_thresh_v2(void)
91a6fb8691SMark Johnston {
92a6fb8691SMark Johnston 	return (CTF_V2_LSTRUCT_THRESH);
93a6fb8691SMark Johnston }
94a6fb8691SMark Johnston 
95a6fb8691SMark Johnston static uint_t
type_info_v2(uint_t kind,uint_t isroot,uint_t len)96a6fb8691SMark Johnston type_info_v2(uint_t kind, uint_t isroot, uint_t len)
97a6fb8691SMark Johnston {
98a6fb8691SMark Johnston 	return (CTF_V2_TYPE_INFO(kind, isroot, len));
99a6fb8691SMark Johnston }
100a6fb8691SMark Johnston 
101a6fb8691SMark Johnston static int
type_isparent_v2(uint_t id)102a6fb8691SMark Johnston type_isparent_v2(uint_t id)
103a6fb8691SMark Johnston {
104a6fb8691SMark Johnston 	return (CTF_V2_TYPE_ISPARENT(id));
105a6fb8691SMark Johnston }
106a6fb8691SMark Johnston 
107a6fb8691SMark Johnston static int
type_ischild_v2(uint_t id)108a6fb8691SMark Johnston type_ischild_v2(uint_t id)
109a6fb8691SMark Johnston {
110a6fb8691SMark Johnston 	return (CTF_V2_TYPE_ISCHILD(id));
111a6fb8691SMark Johnston }
112a6fb8691SMark Johnston 
113a6fb8691SMark Johnston static uint_t
type_to_index_v2(uint_t t)114a6fb8691SMark Johnston type_to_index_v2(uint_t t)
115a6fb8691SMark Johnston {
116a6fb8691SMark Johnston 	return (CTF_V2_TYPE_TO_INDEX(t));
117a6fb8691SMark Johnston }
118a6fb8691SMark Johnston 
119a6fb8691SMark Johnston static uint_t
index_to_type_v2(uint_t id,uint_t child)120a6fb8691SMark Johnston index_to_type_v2(uint_t id, uint_t child)
121a6fb8691SMark Johnston {
122a6fb8691SMark Johnston 	return (CTF_V2_INDEX_TO_TYPE(id, child));
123a6fb8691SMark Johnston }
124a6fb8691SMark Johnston 
125a6fb8691SMark Johnston static uint_t
get_kind_v3(uint_t info)126a6fb8691SMark Johnston get_kind_v3(uint_t info)
127a6fb8691SMark Johnston {
128a6fb8691SMark Johnston 	return (CTF_V3_INFO_KIND(info));
129a6fb8691SMark Johnston }
130a6fb8691SMark Johnston 
131a6fb8691SMark Johnston static uint_t
get_root_v3(uint_t info)132a6fb8691SMark Johnston get_root_v3(uint_t info)
133a6fb8691SMark Johnston {
134a6fb8691SMark Johnston 	return (CTF_V3_INFO_ISROOT(info));
135a6fb8691SMark Johnston }
136a6fb8691SMark Johnston 
137a6fb8691SMark Johnston static uint_t
get_vlen_v3(uint_t info)138a6fb8691SMark Johnston get_vlen_v3(uint_t info)
139a6fb8691SMark Johnston {
140a6fb8691SMark Johnston 	return (CTF_V3_INFO_VLEN(info));
141a6fb8691SMark Johnston }
142a6fb8691SMark Johnston 
143a6fb8691SMark Johnston static uint_t
get_max_vlen_v3(void)144a6fb8691SMark Johnston get_max_vlen_v3(void)
145a6fb8691SMark Johnston {
146a6fb8691SMark Johnston 	return (CTF_V3_MAX_VLEN);
147a6fb8691SMark Johnston }
148a6fb8691SMark Johnston 
149a6fb8691SMark Johnston static uint_t
get_max_size_v3(void)150a6fb8691SMark Johnston get_max_size_v3(void)
151a6fb8691SMark Johnston {
152a6fb8691SMark Johnston 	return (CTF_V3_MAX_SIZE);
153a6fb8691SMark Johnston }
154a6fb8691SMark Johnston 
155a6fb8691SMark Johnston static uint_t
get_max_type_v3(void)156a6fb8691SMark Johnston get_max_type_v3(void)
157a6fb8691SMark Johnston {
158a6fb8691SMark Johnston 	return (CTF_V3_MAX_TYPE);
159a6fb8691SMark Johnston }
160a6fb8691SMark Johnston 
161a6fb8691SMark Johnston static uint_t
get_lsize_sent_v3(void)162a6fb8691SMark Johnston get_lsize_sent_v3(void)
163a6fb8691SMark Johnston {
164a6fb8691SMark Johnston 	return (CTF_V3_LSIZE_SENT);
165a6fb8691SMark Johnston }
166a6fb8691SMark Johnston 
167a6fb8691SMark Johnston static uint_t
get_lstruct_thresh_v3(void)168a6fb8691SMark Johnston get_lstruct_thresh_v3(void)
169a6fb8691SMark Johnston {
170a6fb8691SMark Johnston 	return (CTF_V3_LSTRUCT_THRESH);
171a6fb8691SMark Johnston }
172a6fb8691SMark Johnston 
173a6fb8691SMark Johnston static uint_t
type_info_v3(uint_t kind,uint_t isroot,uint_t len)174a6fb8691SMark Johnston type_info_v3(uint_t kind, uint_t isroot, uint_t len)
175a6fb8691SMark Johnston {
176a6fb8691SMark Johnston 	return (CTF_V3_TYPE_INFO(kind, isroot, len));
177a6fb8691SMark Johnston }
178a6fb8691SMark Johnston 
179a6fb8691SMark Johnston static int
type_isparent_v3(uint_t id)180a6fb8691SMark Johnston type_isparent_v3(uint_t id)
181a6fb8691SMark Johnston {
182a6fb8691SMark Johnston 	return (CTF_V3_TYPE_ISPARENT(id));
183a6fb8691SMark Johnston }
184a6fb8691SMark Johnston 
185a6fb8691SMark Johnston static int
type_ischild_v3(uint_t id)186a6fb8691SMark Johnston type_ischild_v3(uint_t id)
187a6fb8691SMark Johnston {
188a6fb8691SMark Johnston 	return (CTF_V3_TYPE_ISCHILD(id));
189a6fb8691SMark Johnston }
190a6fb8691SMark Johnston 
191a6fb8691SMark Johnston static uint_t
type_to_index_v3(uint_t t)192a6fb8691SMark Johnston type_to_index_v3(uint_t t)
193a6fb8691SMark Johnston {
194a6fb8691SMark Johnston 	return (CTF_V3_TYPE_TO_INDEX(t));
195a6fb8691SMark Johnston }
196a6fb8691SMark Johnston 
197a6fb8691SMark Johnston static uint_t
index_to_type_v3(uint_t id,uint_t child)198a6fb8691SMark Johnston index_to_type_v3(uint_t id, uint_t child)
199a6fb8691SMark Johnston {
200a6fb8691SMark Johnston 	return (CTF_V3_INDEX_TO_TYPE(id, child));
201a6fb8691SMark Johnston }
202a6fb8691SMark Johnston 
203a6fb8691SMark Johnston #define	CTF_FILEOPS_ENTRY(v)				\
204a6fb8691SMark Johnston 	{ 						\
205a6fb8691SMark Johnston 	  .ctfo_get_kind = get_kind_v ## v,		\
206a6fb8691SMark Johnston 	  .ctfo_get_root = get_root_v ## v,		\
207a6fb8691SMark Johnston 	  .ctfo_get_vlen = get_vlen_v ## v,		\
208a6fb8691SMark Johnston 	  .ctfo_get_max_vlen = get_max_vlen_v ## v,	\
209a6fb8691SMark Johnston 	  .ctfo_get_max_size = get_max_size_v ## v,	\
210a6fb8691SMark Johnston 	  .ctfo_get_max_type = get_max_type_v ## v,	\
211a6fb8691SMark Johnston 	  .ctfo_get_lsize_sent = get_lsize_sent_v ## v,	\
212a6fb8691SMark Johnston 	  .ctfo_get_lstruct_thresh = get_lstruct_thresh_v ## v,	\
213a6fb8691SMark Johnston 	  .ctfo_type_info = type_info_v ## v,		\
214a6fb8691SMark Johnston 	  .ctfo_type_isparent = type_isparent_v ## v,	\
215a6fb8691SMark Johnston 	  .ctfo_type_ischild = type_ischild_v ## v,	\
216a6fb8691SMark Johnston 	  .ctfo_type_to_index = type_to_index_v ## v,	\
217a6fb8691SMark Johnston 	  .ctfo_index_to_type = index_to_type_v ## v	\
218d876124dSJohn Birrell 	}
219d876124dSJohn Birrell 
220d876124dSJohn Birrell static const ctf_fileops_t ctf_fileops[] = {
221d876124dSJohn Birrell 	{ NULL, NULL },
2227db423d6SMark Johnston 	{ NULL, NULL },
223a6fb8691SMark Johnston 	CTF_FILEOPS_ENTRY(2),
224a6fb8691SMark Johnston 	CTF_FILEOPS_ENTRY(3),
225d876124dSJohn Birrell };
226d876124dSJohn Birrell 
227d876124dSJohn Birrell /*
228d876124dSJohn Birrell  * Convert a 32-bit ELF symbol into GElf (Elf64) and return a pointer to it.
229d876124dSJohn Birrell  */
230d876124dSJohn Birrell static Elf64_Sym *
sym_to_gelf(const Elf32_Sym * src,Elf64_Sym * dst)231d876124dSJohn Birrell sym_to_gelf(const Elf32_Sym *src, Elf64_Sym *dst)
232d876124dSJohn Birrell {
233d876124dSJohn Birrell 	dst->st_name = src->st_name;
234d876124dSJohn Birrell 	dst->st_value = src->st_value;
235d876124dSJohn Birrell 	dst->st_size = src->st_size;
236d876124dSJohn Birrell 	dst->st_info = src->st_info;
237d876124dSJohn Birrell 	dst->st_other = src->st_other;
238d876124dSJohn Birrell 	dst->st_shndx = src->st_shndx;
239d876124dSJohn Birrell 
240d876124dSJohn Birrell 	return (dst);
241d876124dSJohn Birrell }
242d876124dSJohn Birrell 
243d876124dSJohn Birrell /*
244d876124dSJohn Birrell  * Initialize the symtab translation table by filling each entry with the
245d876124dSJohn Birrell  * offset of the CTF type or function data corresponding to each STT_FUNC or
246d876124dSJohn Birrell  * STT_OBJECT entry in the symbol table.
247d876124dSJohn Birrell  */
248d876124dSJohn Birrell static int
init_symtab(ctf_file_t * fp,const ctf_header_t * hp,const ctf_sect_t * sp,const ctf_sect_t * strp)249d876124dSJohn Birrell init_symtab(ctf_file_t *fp, const ctf_header_t *hp,
250d876124dSJohn Birrell     const ctf_sect_t *sp, const ctf_sect_t *strp)
251d876124dSJohn Birrell {
252d876124dSJohn Birrell 	const uchar_t *symp = sp->cts_data;
253d876124dSJohn Birrell 	uint_t *xp = fp->ctf_sxlate;
254d876124dSJohn Birrell 	uint_t *xend = xp + fp->ctf_nsyms;
255d876124dSJohn Birrell 
256d876124dSJohn Birrell 	uint_t objtoff = hp->cth_objtoff;
257d876124dSJohn Birrell 	uint_t funcoff = hp->cth_funcoff;
258d876124dSJohn Birrell 
259a6fb8691SMark Johnston 	uint_t info, vlen;
260a6fb8691SMark Johnston 
261d876124dSJohn Birrell 	Elf64_Sym sym, *gsp;
262d876124dSJohn Birrell 	const char *name;
263d876124dSJohn Birrell 
264d876124dSJohn Birrell 	/*
265d876124dSJohn Birrell 	 * The CTF data object and function type sections are ordered to match
266d876124dSJohn Birrell 	 * the relative order of the respective symbol types in the symtab.
267d876124dSJohn Birrell 	 * If no type information is available for a symbol table entry, a
268d876124dSJohn Birrell 	 * pad is inserted in the CTF section.  As a further optimization,
269d876124dSJohn Birrell 	 * anonymous or undefined symbols are omitted from the CTF data.
270d876124dSJohn Birrell 	 */
271d876124dSJohn Birrell 	for (; xp < xend; xp++, symp += sp->cts_entsize) {
272d876124dSJohn Birrell 		if (sp->cts_entsize == sizeof (Elf32_Sym))
273d876124dSJohn Birrell 			gsp = sym_to_gelf((Elf32_Sym *)(uintptr_t)symp, &sym);
274d876124dSJohn Birrell 		else
275d876124dSJohn Birrell 			gsp = (Elf64_Sym *)(uintptr_t)symp;
276d876124dSJohn Birrell 
277d876124dSJohn Birrell 		if (gsp->st_name < strp->cts_size)
278d876124dSJohn Birrell 			name = (const char *)strp->cts_data + gsp->st_name;
279d876124dSJohn Birrell 		else
280d876124dSJohn Birrell 			name = _CTF_NULLSTR;
281d876124dSJohn Birrell 
282d876124dSJohn Birrell 		if (gsp->st_name == 0 || gsp->st_shndx == SHN_UNDEF ||
283d876124dSJohn Birrell 		    strcmp(name, "_START_") == 0 ||
284d876124dSJohn Birrell 		    strcmp(name, "_END_") == 0) {
285d876124dSJohn Birrell 			*xp = -1u;
286d876124dSJohn Birrell 			continue;
287d876124dSJohn Birrell 		}
288d876124dSJohn Birrell 
289d876124dSJohn Birrell 		switch (ELF64_ST_TYPE(gsp->st_info)) {
290d876124dSJohn Birrell 		case STT_OBJECT:
291d876124dSJohn Birrell 			if (objtoff >= hp->cth_funcoff ||
292d876124dSJohn Birrell 			    (gsp->st_shndx == SHN_ABS && gsp->st_value == 0)) {
293d876124dSJohn Birrell 				*xp = -1u;
294d876124dSJohn Birrell 				break;
295d876124dSJohn Birrell 			}
296d876124dSJohn Birrell 
297d876124dSJohn Birrell 			*xp = objtoff;
298a6fb8691SMark Johnston 			objtoff += fp->ctf_idwidth;
299d876124dSJohn Birrell 			break;
300d876124dSJohn Birrell 
301d876124dSJohn Birrell 		case STT_FUNC:
302d876124dSJohn Birrell 			if (funcoff >= hp->cth_typeoff) {
303d876124dSJohn Birrell 				*xp = -1u;
304d876124dSJohn Birrell 				break;
305d876124dSJohn Birrell 			}
306d876124dSJohn Birrell 
307d876124dSJohn Birrell 			*xp = funcoff;
308d876124dSJohn Birrell 
309a6fb8691SMark Johnston 			info = *(uint_t *)((uintptr_t)fp->ctf_buf + funcoff);
310d876124dSJohn Birrell 			vlen = LCTF_INFO_VLEN(fp, info);
311d876124dSJohn Birrell 
312d876124dSJohn Birrell 			/*
313d876124dSJohn Birrell 			 * If we encounter a zero pad at the end, just skip it.
314d876124dSJohn Birrell 			 * Otherwise skip over the function and its return type
315d876124dSJohn Birrell 			 * (+2) and the argument list (vlen).
316d876124dSJohn Birrell 			 */
317d876124dSJohn Birrell 			if (LCTF_INFO_KIND(fp, info) == CTF_K_UNKNOWN &&
318d876124dSJohn Birrell 			    vlen == 0)
319a6fb8691SMark Johnston 				funcoff += fp->ctf_idwidth;
320d876124dSJohn Birrell 			else
321a6fb8691SMark Johnston 				funcoff +=
322a6fb8691SMark Johnston 				    roundup2(fp->ctf_idwidth * (vlen + 2), 4);
323d876124dSJohn Birrell 			break;
324d876124dSJohn Birrell 
325d876124dSJohn Birrell 		default:
326d876124dSJohn Birrell 			*xp = -1u;
327d876124dSJohn Birrell 			break;
328d876124dSJohn Birrell 		}
329d876124dSJohn Birrell 	}
330d876124dSJohn Birrell 
331d876124dSJohn Birrell 	ctf_dprintf("loaded %lu symtab entries\n", fp->ctf_nsyms);
332d876124dSJohn Birrell 	return (0);
333d876124dSJohn Birrell }
334d876124dSJohn Birrell 
335d876124dSJohn Birrell /*
336d876124dSJohn Birrell  * Initialize the type ID translation table with the byte offset of each type,
337d876124dSJohn Birrell  * and initialize the hash tables of each named type.
338d876124dSJohn Birrell  */
339d876124dSJohn Birrell static int
init_types(ctf_file_t * fp,const ctf_header_t * cth)340d876124dSJohn Birrell init_types(ctf_file_t *fp, const ctf_header_t *cth)
341d876124dSJohn Birrell {
342a6fb8691SMark Johnston 	const void *tbuf = (const void *)(fp->ctf_buf + cth->cth_typeoff);
343a6fb8691SMark Johnston 	const void *tend = (const void *)(fp->ctf_buf + cth->cth_stroff);
344d876124dSJohn Birrell 
345d876124dSJohn Birrell 	ulong_t pop[CTF_K_MAX + 1] = { 0 };
346a6fb8691SMark Johnston 	const void *tp;
347d876124dSJohn Birrell 	ctf_hash_t *hp;
348a6fb8691SMark Johnston 	uint_t id, dst;
349d876124dSJohn Birrell 	uint_t *xp;
350d876124dSJohn Birrell 
351d876124dSJohn Birrell 	/*
352d876124dSJohn Birrell 	 * We initially determine whether the container is a child or a parent
353d876124dSJohn Birrell 	 * based on the value of cth_parname.  To support containers that pre-
354d876124dSJohn Birrell 	 * date cth_parname, we also scan the types themselves for references
355d876124dSJohn Birrell 	 * to values in the range reserved for child types in our first pass.
356d876124dSJohn Birrell 	 */
357d876124dSJohn Birrell 	int child = cth->cth_parname != 0;
358d876124dSJohn Birrell 	int nlstructs = 0, nlunions = 0;
359d876124dSJohn Birrell 	int err;
360d876124dSJohn Birrell 
361d876124dSJohn Birrell 	/*
362d876124dSJohn Birrell 	 * We make two passes through the entire type section.  In this first
363d876124dSJohn Birrell 	 * pass, we count the number of each type and the total number of types.
364d876124dSJohn Birrell 	 */
365d876124dSJohn Birrell 	for (tp = tbuf; tp < tend; fp->ctf_typemax++) {
366d876124dSJohn Birrell 		ssize_t size, increment;
367d876124dSJohn Birrell 
368d876124dSJohn Birrell 		size_t vbytes;
369a6fb8691SMark Johnston 		uint_t kind, n, type, vlen;
370d876124dSJohn Birrell 
371d876124dSJohn Birrell 		(void) ctf_get_ctt_size(fp, tp, &size, &increment);
372a6fb8691SMark Johnston 		ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
373a6fb8691SMark Johnston 		ctf_get_ctt_index(fp, tp, NULL, &type, NULL);
374d876124dSJohn Birrell 
375d876124dSJohn Birrell 		switch (kind) {
376d876124dSJohn Birrell 		case CTF_K_INTEGER:
377d876124dSJohn Birrell 		case CTF_K_FLOAT:
378d876124dSJohn Birrell 			vbytes = sizeof (uint_t);
379d876124dSJohn Birrell 			break;
380d876124dSJohn Birrell 		case CTF_K_ARRAY:
381a6fb8691SMark Johnston 			if (fp->ctf_version == CTF_VERSION_2)
382a6fb8691SMark Johnston 				vbytes = sizeof (struct ctf_array_v2);
383a6fb8691SMark Johnston 			else
384a6fb8691SMark Johnston 				vbytes = sizeof (struct ctf_array_v3);
385d876124dSJohn Birrell 			break;
386d876124dSJohn Birrell 		case CTF_K_FUNCTION:
387a6fb8691SMark Johnston 			vbytes = roundup2(fp->ctf_idwidth * vlen, 4);
388d876124dSJohn Birrell 			break;
389d876124dSJohn Birrell 		case CTF_K_STRUCT:
390a6fb8691SMark Johnston 		case CTF_K_UNION: {
391a6fb8691SMark Johnston 			size_t increment1;
392a6fb8691SMark Johnston 			uint_t type;
393a6fb8691SMark Johnston 			const void *mp =
394a6fb8691SMark Johnston 			    (const void *)((uintptr_t)tp + increment);
395d876124dSJohn Birrell 
396a6fb8691SMark Johnston 			vbytes = 0;
397a6fb8691SMark Johnston 			for (n = vlen; n != 0; n--, mp += increment1) {
398a6fb8691SMark Johnston 				ctf_get_ctm_info(fp, mp, size, &increment1, &type,
399a6fb8691SMark Johnston 				    NULL, NULL);
400a6fb8691SMark Johnston 				child |= LCTF_TYPE_ISCHILD(fp, type);
401a6fb8691SMark Johnston 				vbytes += increment1;
402d876124dSJohn Birrell 			}
403d876124dSJohn Birrell 			break;
404a6fb8691SMark Johnston 		}
405d876124dSJohn Birrell 		case CTF_K_ENUM:
406d876124dSJohn Birrell 			vbytes = sizeof (ctf_enum_t) * vlen;
407d876124dSJohn Birrell 			break;
408d876124dSJohn Birrell 		case CTF_K_FORWARD:
409d876124dSJohn Birrell 			/*
410d876124dSJohn Birrell 			 * For forward declarations, ctt_type is the CTF_K_*
411d876124dSJohn Birrell 			 * kind for the tag, so bump that population count too.
412d876124dSJohn Birrell 			 * If ctt_type is unknown, treat the tag as a struct.
413d876124dSJohn Birrell 			 */
414a6fb8691SMark Johnston 			if (type == CTF_K_UNKNOWN || type >= CTF_K_MAX)
415d876124dSJohn Birrell 				pop[CTF_K_STRUCT]++;
416d876124dSJohn Birrell 			else
417a6fb8691SMark Johnston 				pop[type]++;
418d876124dSJohn Birrell 			/*FALLTHRU*/
419d876124dSJohn Birrell 		case CTF_K_UNKNOWN:
420d876124dSJohn Birrell 			vbytes = 0;
421d876124dSJohn Birrell 			break;
422d876124dSJohn Birrell 		case CTF_K_POINTER:
423d876124dSJohn Birrell 		case CTF_K_TYPEDEF:
424d876124dSJohn Birrell 		case CTF_K_VOLATILE:
425d876124dSJohn Birrell 		case CTF_K_CONST:
426d876124dSJohn Birrell 		case CTF_K_RESTRICT:
427a6fb8691SMark Johnston 			child |= LCTF_TYPE_ISCHILD(fp, type);
428d876124dSJohn Birrell 			vbytes = 0;
429d876124dSJohn Birrell 			break;
430d876124dSJohn Birrell 		default:
431d876124dSJohn Birrell 			ctf_dprintf("detected invalid CTF kind -- %u\n", kind);
432d876124dSJohn Birrell 			return (ECTF_CORRUPT);
433d876124dSJohn Birrell 		}
434a6fb8691SMark Johnston 		tp = (const void *)((uintptr_t)tp + increment + vbytes);
435d876124dSJohn Birrell 		pop[kind]++;
436d876124dSJohn Birrell 	}
437d876124dSJohn Birrell 
438d876124dSJohn Birrell 	/*
439d876124dSJohn Birrell 	 * If we detected a reference to a child type ID, then we know this
440d876124dSJohn Birrell 	 * container is a child and may have a parent's types imported later.
441d876124dSJohn Birrell 	 */
442d876124dSJohn Birrell 	if (child) {
443d876124dSJohn Birrell 		ctf_dprintf("CTF container %p is a child\n", (void *)fp);
444d876124dSJohn Birrell 		fp->ctf_flags |= LCTF_CHILD;
445d876124dSJohn Birrell 	} else
446d876124dSJohn Birrell 		ctf_dprintf("CTF container %p is a parent\n", (void *)fp);
447d876124dSJohn Birrell 
448d876124dSJohn Birrell 	/*
449d876124dSJohn Birrell 	 * Now that we've counted up the number of each type, we can allocate
450d876124dSJohn Birrell 	 * the hash tables, type translation table, and pointer table.
451d876124dSJohn Birrell 	 */
452d876124dSJohn Birrell 	if ((err = ctf_hash_create(&fp->ctf_structs, pop[CTF_K_STRUCT])) != 0)
453d876124dSJohn Birrell 		return (err);
454d876124dSJohn Birrell 
455d876124dSJohn Birrell 	if ((err = ctf_hash_create(&fp->ctf_unions, pop[CTF_K_UNION])) != 0)
456d876124dSJohn Birrell 		return (err);
457d876124dSJohn Birrell 
458d876124dSJohn Birrell 	if ((err = ctf_hash_create(&fp->ctf_enums, pop[CTF_K_ENUM])) != 0)
459d876124dSJohn Birrell 		return (err);
460d876124dSJohn Birrell 
461d876124dSJohn Birrell 	if ((err = ctf_hash_create(&fp->ctf_names,
462d876124dSJohn Birrell 	    pop[CTF_K_INTEGER] + pop[CTF_K_FLOAT] + pop[CTF_K_FUNCTION] +
463d876124dSJohn Birrell 	    pop[CTF_K_TYPEDEF] + pop[CTF_K_POINTER] + pop[CTF_K_VOLATILE] +
464d876124dSJohn Birrell 	    pop[CTF_K_CONST] + pop[CTF_K_RESTRICT])) != 0)
465d876124dSJohn Birrell 		return (err);
466d876124dSJohn Birrell 
467d876124dSJohn Birrell 	fp->ctf_txlate = ctf_alloc(sizeof (uint_t) * (fp->ctf_typemax + 1));
468a6fb8691SMark Johnston 	fp->ctf_ptrtab = ctf_alloc(sizeof (uint_t) * (fp->ctf_typemax + 1));
469d876124dSJohn Birrell 
470d876124dSJohn Birrell 	if (fp->ctf_txlate == NULL || fp->ctf_ptrtab == NULL)
471d876124dSJohn Birrell 		return (EAGAIN); /* memory allocation failed */
472d876124dSJohn Birrell 
473d876124dSJohn Birrell 	xp = fp->ctf_txlate;
474d876124dSJohn Birrell 	*xp++ = 0; /* type id 0 is used as a sentinel value */
475d876124dSJohn Birrell 
476d876124dSJohn Birrell 	bzero(fp->ctf_txlate, sizeof (uint_t) * (fp->ctf_typemax + 1));
477a6fb8691SMark Johnston 	bzero(fp->ctf_ptrtab, sizeof (uint_t) * (fp->ctf_typemax + 1));
478d876124dSJohn Birrell 
479d876124dSJohn Birrell 	/*
480d876124dSJohn Birrell 	 * In the second pass through the types, we fill in each entry of the
481d876124dSJohn Birrell 	 * type and pointer tables and add names to the appropriate hashes.
482d876124dSJohn Birrell 	 */
483d876124dSJohn Birrell 	for (id = 1, tp = tbuf; tp < tend; xp++, id++) {
484a6fb8691SMark Johnston 		const struct ctf_type_v3 *ctt = tp;
485a6fb8691SMark Johnston 		uint_t kind, type, vlen;
486d876124dSJohn Birrell 		ssize_t size, increment;
487d876124dSJohn Birrell 
488d876124dSJohn Birrell 		const char *name;
489d876124dSJohn Birrell 		size_t vbytes;
490d876124dSJohn Birrell 		ctf_helem_t *hep;
491d876124dSJohn Birrell 		ctf_encoding_t cte;
492d876124dSJohn Birrell 
493d876124dSJohn Birrell 		(void) ctf_get_ctt_size(fp, tp, &size, &increment);
494a6fb8691SMark Johnston 		ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
495a6fb8691SMark Johnston 		ctf_get_ctt_index(fp, tp, NULL, &type, NULL);
496a6fb8691SMark Johnston 		name = ctf_type_rname(fp, tp);
497d876124dSJohn Birrell 
498d876124dSJohn Birrell 		switch (kind) {
499d876124dSJohn Birrell 		case CTF_K_INTEGER:
500d876124dSJohn Birrell 		case CTF_K_FLOAT:
501d876124dSJohn Birrell 			/*
502d876124dSJohn Birrell 			 * Only insert a new integer base type definition if
503d876124dSJohn Birrell 			 * this type name has not been defined yet.  We re-use
504d876124dSJohn Birrell 			 * the names with different encodings for bit-fields.
505d876124dSJohn Birrell 			 */
506d876124dSJohn Birrell 			if ((hep = ctf_hash_lookup(&fp->ctf_names, fp,
507d876124dSJohn Birrell 			    name, strlen(name))) == NULL) {
508d876124dSJohn Birrell 				err = ctf_hash_insert(&fp->ctf_names, fp,
509a6fb8691SMark Johnston 				    LCTF_INDEX_TO_TYPE(fp, id, child),
510a6fb8691SMark Johnston 				    ctt->ctt_name);
511d876124dSJohn Birrell 				if (err != 0 && err != ECTF_STRTAB)
512d876124dSJohn Birrell 					return (err);
513d876124dSJohn Birrell 			} else if (ctf_type_encoding(fp, hep->h_type,
514d876124dSJohn Birrell 			    &cte) == 0 && cte.cte_bits == 0) {
515d876124dSJohn Birrell 				/*
516d876124dSJohn Birrell 				 * Work-around SOS8 stabs bug: replace existing
517d876124dSJohn Birrell 				 * intrinsic w/ same name if it was zero bits.
518d876124dSJohn Birrell 				 */
519a6fb8691SMark Johnston 				hep->h_type = LCTF_INDEX_TO_TYPE(fp, id, child);
520d876124dSJohn Birrell 			}
521d876124dSJohn Birrell 			vbytes = sizeof (uint_t);
522d876124dSJohn Birrell 			break;
523d876124dSJohn Birrell 
524d876124dSJohn Birrell 		case CTF_K_ARRAY:
525a6fb8691SMark Johnston 			if (fp->ctf_version == CTF_VERSION_2)
526a6fb8691SMark Johnston 				vbytes = sizeof (struct ctf_array_v2);
527a6fb8691SMark Johnston 			else
528a6fb8691SMark Johnston 				vbytes = sizeof (struct ctf_array_v3);
529d876124dSJohn Birrell 			break;
530d876124dSJohn Birrell 
531d876124dSJohn Birrell 		case CTF_K_FUNCTION:
532d876124dSJohn Birrell 			err = ctf_hash_insert(&fp->ctf_names, fp,
533a6fb8691SMark Johnston 			    LCTF_INDEX_TO_TYPE(fp, id, child), ctt->ctt_name);
534d876124dSJohn Birrell 			if (err != 0 && err != ECTF_STRTAB)
535d876124dSJohn Birrell 				return (err);
536a6fb8691SMark Johnston 			vbytes = roundup2(fp->ctf_idwidth * vlen, 4);
537d876124dSJohn Birrell 			break;
538d876124dSJohn Birrell 
539d876124dSJohn Birrell 		case CTF_K_STRUCT:
540d876124dSJohn Birrell 			err = ctf_hash_define(&fp->ctf_structs, fp,
541a6fb8691SMark Johnston 			    LCTF_INDEX_TO_TYPE(fp, id, child), ctt->ctt_name);
542d876124dSJohn Birrell 
543d876124dSJohn Birrell 			if (err != 0 && err != ECTF_STRTAB)
544d876124dSJohn Birrell 				return (err);
545d876124dSJohn Birrell 
546a6fb8691SMark Johnston 			if (fp->ctf_version == CTF_VERSION_2) {
547a6fb8691SMark Johnston 				if (size < LCTF_LSTRUCT_THRESH(fp))
548a6fb8691SMark Johnston 					vbytes = sizeof (struct ctf_member_v2) *
549a6fb8691SMark Johnston 					    vlen;
550d876124dSJohn Birrell 				else {
551a6fb8691SMark Johnston 					vbytes =
552a6fb8691SMark Johnston 					    sizeof (struct ctf_lmember_v2) *
553a6fb8691SMark Johnston 					    vlen;
554d876124dSJohn Birrell 					nlstructs++;
555d876124dSJohn Birrell 				}
556a6fb8691SMark Johnston 			} else {
557a6fb8691SMark Johnston 				if (size < LCTF_LSTRUCT_THRESH(fp))
558a6fb8691SMark Johnston 					vbytes = sizeof (struct ctf_member_v3) *
559a6fb8691SMark Johnston 					    vlen;
560a6fb8691SMark Johnston 				else {
561a6fb8691SMark Johnston 					vbytes =
562a6fb8691SMark Johnston 					    sizeof (struct ctf_lmember_v3) *
563a6fb8691SMark Johnston 					    vlen;
564a6fb8691SMark Johnston 					nlstructs++;
565a6fb8691SMark Johnston 				}
566a6fb8691SMark Johnston 			}
567d876124dSJohn Birrell 			break;
568d876124dSJohn Birrell 
569d876124dSJohn Birrell 		case CTF_K_UNION:
570d876124dSJohn Birrell 			err = ctf_hash_define(&fp->ctf_unions, fp,
571a6fb8691SMark Johnston 			    LCTF_INDEX_TO_TYPE(fp, id, child), ctt->ctt_name);
572d876124dSJohn Birrell 
573d876124dSJohn Birrell 			if (err != 0 && err != ECTF_STRTAB)
574d876124dSJohn Birrell 				return (err);
575d876124dSJohn Birrell 
576a6fb8691SMark Johnston 			if (fp->ctf_version == CTF_VERSION_2) {
577a6fb8691SMark Johnston 				if (size < LCTF_LSTRUCT_THRESH(fp))
578a6fb8691SMark Johnston 					vbytes = sizeof (struct ctf_member_v2) *
579a6fb8691SMark Johnston 					    vlen;
580d876124dSJohn Birrell 				else {
581a6fb8691SMark Johnston 					vbytes =
582a6fb8691SMark Johnston 					    sizeof (struct ctf_lmember_v2) *
583a6fb8691SMark Johnston 					    vlen;
584d876124dSJohn Birrell 					nlunions++;
585d876124dSJohn Birrell 				}
586a6fb8691SMark Johnston 			} else {
587a6fb8691SMark Johnston 				if (size < LCTF_LSTRUCT_THRESH(fp))
588a6fb8691SMark Johnston 					vbytes = sizeof (struct ctf_member_v3) *
589a6fb8691SMark Johnston 					    vlen;
590a6fb8691SMark Johnston 				else {
591a6fb8691SMark Johnston 					vbytes =
592a6fb8691SMark Johnston 					    sizeof (struct ctf_lmember_v3) *
593a6fb8691SMark Johnston 					    vlen;
594a6fb8691SMark Johnston 					nlunions++;
595a6fb8691SMark Johnston 				}
596a6fb8691SMark Johnston 			}
597d876124dSJohn Birrell 			break;
598d876124dSJohn Birrell 
599d876124dSJohn Birrell 		case CTF_K_ENUM:
600d876124dSJohn Birrell 			err = ctf_hash_define(&fp->ctf_enums, fp,
601a6fb8691SMark Johnston 			    LCTF_INDEX_TO_TYPE(fp, id, child), ctt->ctt_name);
602d876124dSJohn Birrell 
603d876124dSJohn Birrell 			if (err != 0 && err != ECTF_STRTAB)
604d876124dSJohn Birrell 				return (err);
605d876124dSJohn Birrell 
606d876124dSJohn Birrell 			vbytes = sizeof (ctf_enum_t) * vlen;
607d876124dSJohn Birrell 			break;
608d876124dSJohn Birrell 
609d876124dSJohn Birrell 		case CTF_K_TYPEDEF:
610d876124dSJohn Birrell 			err = ctf_hash_insert(&fp->ctf_names, fp,
611a6fb8691SMark Johnston 			    LCTF_INDEX_TO_TYPE(fp, id, child), ctt->ctt_name);
612d876124dSJohn Birrell 			if (err != 0 && err != ECTF_STRTAB)
613d876124dSJohn Birrell 				return (err);
614d876124dSJohn Birrell 			vbytes = 0;
615d876124dSJohn Birrell 			break;
616d876124dSJohn Birrell 
617d876124dSJohn Birrell 		case CTF_K_FORWARD:
618d876124dSJohn Birrell 			/*
619d876124dSJohn Birrell 			 * Only insert forward tags into the given hash if the
620d876124dSJohn Birrell 			 * type or tag name is not already present.
621d876124dSJohn Birrell 			 */
622a6fb8691SMark Johnston 			switch (type) {
623d876124dSJohn Birrell 			case CTF_K_STRUCT:
624d876124dSJohn Birrell 				hp = &fp->ctf_structs;
625d876124dSJohn Birrell 				break;
626d876124dSJohn Birrell 			case CTF_K_UNION:
627d876124dSJohn Birrell 				hp = &fp->ctf_unions;
628d876124dSJohn Birrell 				break;
629d876124dSJohn Birrell 			case CTF_K_ENUM:
630d876124dSJohn Birrell 				hp = &fp->ctf_enums;
631d876124dSJohn Birrell 				break;
632d876124dSJohn Birrell 			default:
633d876124dSJohn Birrell 				hp = &fp->ctf_structs;
634d876124dSJohn Birrell 			}
635d876124dSJohn Birrell 
636d876124dSJohn Birrell 			if (ctf_hash_lookup(hp, fp,
637d876124dSJohn Birrell 			    name, strlen(name)) == NULL) {
638d876124dSJohn Birrell 				err = ctf_hash_insert(hp, fp,
639a6fb8691SMark Johnston 				    LCTF_INDEX_TO_TYPE(fp, id, child),
640a6fb8691SMark Johnston 				    ctt->ctt_name);
641d876124dSJohn Birrell 				if (err != 0 && err != ECTF_STRTAB)
642d876124dSJohn Birrell 					return (err);
643d876124dSJohn Birrell 			}
644d876124dSJohn Birrell 			vbytes = 0;
645d876124dSJohn Birrell 			break;
646d876124dSJohn Birrell 
647d876124dSJohn Birrell 		case CTF_K_POINTER:
648d876124dSJohn Birrell 			/*
649d876124dSJohn Birrell 			 * If the type referenced by the pointer is in this CTF
650d876124dSJohn Birrell 			 * container, then store the index of the pointer type
651d876124dSJohn Birrell 			 * in fp->ctf_ptrtab[ index of referenced type ].
652d876124dSJohn Birrell 			 */
653a6fb8691SMark Johnston 			if (LCTF_TYPE_ISCHILD(fp, type) == child &&
654a6fb8691SMark Johnston 			    LCTF_TYPE_TO_INDEX(fp, type) <= fp->ctf_typemax)
655d876124dSJohn Birrell 				fp->ctf_ptrtab[
656a6fb8691SMark Johnston 				    LCTF_TYPE_TO_INDEX(fp, type)] = id;
657d876124dSJohn Birrell 			/*FALLTHRU*/
658d876124dSJohn Birrell 
659d876124dSJohn Birrell 		case CTF_K_VOLATILE:
660d876124dSJohn Birrell 		case CTF_K_CONST:
661d876124dSJohn Birrell 		case CTF_K_RESTRICT:
662d876124dSJohn Birrell 			err = ctf_hash_insert(&fp->ctf_names, fp,
663a6fb8691SMark Johnston 			    LCTF_INDEX_TO_TYPE(fp, id, child), ctt->ctt_name);
664d876124dSJohn Birrell 			if (err != 0 && err != ECTF_STRTAB)
665d876124dSJohn Birrell 				return (err);
666d876124dSJohn Birrell 			/*FALLTHRU*/
667d876124dSJohn Birrell 
668d876124dSJohn Birrell 		default:
669d876124dSJohn Birrell 			vbytes = 0;
670d876124dSJohn Birrell 			break;
671d876124dSJohn Birrell 		}
672d876124dSJohn Birrell 
673d876124dSJohn Birrell 		*xp = (uint_t)((uintptr_t)tp - (uintptr_t)fp->ctf_buf);
674a6fb8691SMark Johnston 		tp = (const void *)((uintptr_t)tp + increment + vbytes);
675d876124dSJohn Birrell 	}
676d876124dSJohn Birrell 
677d876124dSJohn Birrell 	ctf_dprintf("%lu total types processed\n", fp->ctf_typemax);
678d876124dSJohn Birrell 	ctf_dprintf("%u enum names hashed\n", ctf_hash_size(&fp->ctf_enums));
679d876124dSJohn Birrell 	ctf_dprintf("%u struct names hashed (%d long)\n",
680d876124dSJohn Birrell 	    ctf_hash_size(&fp->ctf_structs), nlstructs);
681d876124dSJohn Birrell 	ctf_dprintf("%u union names hashed (%d long)\n",
682d876124dSJohn Birrell 	    ctf_hash_size(&fp->ctf_unions), nlunions);
683d876124dSJohn Birrell 	ctf_dprintf("%u base type names hashed\n",
684d876124dSJohn Birrell 	    ctf_hash_size(&fp->ctf_names));
685d876124dSJohn Birrell 
686d876124dSJohn Birrell 	/*
687d876124dSJohn Birrell 	 * Make an additional pass through the pointer table to find pointers
688d876124dSJohn Birrell 	 * that point to anonymous typedef nodes.  If we find one, modify the
689d876124dSJohn Birrell 	 * pointer table so that the pointer is also known to point to the
690d876124dSJohn Birrell 	 * node that is referenced by the anonymous typedef node.
691d876124dSJohn Birrell 	 */
692d876124dSJohn Birrell 	for (id = 1; id <= fp->ctf_typemax; id++) {
693d876124dSJohn Birrell 		if ((dst = fp->ctf_ptrtab[id]) != 0) {
694a6fb8691SMark Johnston 			uint_t index, kind;
695a6fb8691SMark Johnston 			int ischild;
696d876124dSJohn Birrell 
697a6fb8691SMark Johnston 			tp = LCTF_INDEX_TO_TYPEPTR(fp, id);
698a6fb8691SMark Johnston 			ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
699a6fb8691SMark Johnston 			ctf_get_ctt_index(fp, tp, &index, NULL, &ischild);
700a6fb8691SMark Johnston 
701a6fb8691SMark Johnston 			if (kind == CTF_K_TYPEDEF &&
702a6fb8691SMark Johnston 			    strcmp(ctf_type_rname(fp, tp), "") == 0 &&
703a6fb8691SMark Johnston 			    ischild == child && index <= fp->ctf_typemax)
704a6fb8691SMark Johnston 				fp->ctf_ptrtab[index] = dst;
705d876124dSJohn Birrell 		}
706d876124dSJohn Birrell 	}
707d876124dSJohn Birrell 
708d876124dSJohn Birrell 	return (0);
709d876124dSJohn Birrell }
710d876124dSJohn Birrell 
711d876124dSJohn Birrell /*
712d876124dSJohn Birrell  * Decode the specified CTF buffer and optional symbol table and create a new
713d876124dSJohn Birrell  * CTF container representing the symbolic debugging information.  This code
714d876124dSJohn Birrell  * can be used directly by the debugger, or it can be used as the engine for
715d876124dSJohn Birrell  * ctf_fdopen() or ctf_open(), below.
716d876124dSJohn Birrell  */
717d876124dSJohn Birrell ctf_file_t *
ctf_bufopen(const ctf_sect_t * ctfsect,const ctf_sect_t * symsect,const ctf_sect_t * strsect,int * errp)718d876124dSJohn Birrell ctf_bufopen(const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
719d876124dSJohn Birrell     const ctf_sect_t *strsect, int *errp)
720d876124dSJohn Birrell {
721d876124dSJohn Birrell 	const ctf_preamble_t *pp;
722d876124dSJohn Birrell 	ctf_header_t hp;
723d876124dSJohn Birrell 	ctf_file_t *fp;
724d876124dSJohn Birrell 	void *buf, *base;
725d876124dSJohn Birrell 	size_t size, hdrsz;
726d876124dSJohn Birrell 	int err;
727d876124dSJohn Birrell 
728d876124dSJohn Birrell 	if (ctfsect == NULL || ((symsect == NULL) != (strsect == NULL)))
729d876124dSJohn Birrell 		return (ctf_set_open_errno(errp, EINVAL));
730d876124dSJohn Birrell 
731d876124dSJohn Birrell 	if (symsect != NULL && symsect->cts_entsize != sizeof (Elf32_Sym) &&
732d876124dSJohn Birrell 	    symsect->cts_entsize != sizeof (Elf64_Sym))
733d876124dSJohn Birrell 		return (ctf_set_open_errno(errp, ECTF_SYMTAB));
734d876124dSJohn Birrell 
735d876124dSJohn Birrell 	if (symsect != NULL && symsect->cts_data == NULL)
736d876124dSJohn Birrell 		return (ctf_set_open_errno(errp, ECTF_SYMBAD));
737d876124dSJohn Birrell 
738d876124dSJohn Birrell 	if (strsect != NULL && strsect->cts_data == NULL)
739d876124dSJohn Birrell 		return (ctf_set_open_errno(errp, ECTF_STRBAD));
740d876124dSJohn Birrell 
741d876124dSJohn Birrell 	if (ctfsect->cts_size < sizeof (ctf_preamble_t))
742d876124dSJohn Birrell 		return (ctf_set_open_errno(errp, ECTF_NOCTFBUF));
743d876124dSJohn Birrell 
744d876124dSJohn Birrell 	pp = (const ctf_preamble_t *)ctfsect->cts_data;
745d876124dSJohn Birrell 
746d876124dSJohn Birrell 	ctf_dprintf("ctf_bufopen: magic=0x%x version=%u\n",
747d876124dSJohn Birrell 	    pp->ctp_magic, pp->ctp_version);
748d876124dSJohn Birrell 
749d876124dSJohn Birrell 	/*
750d876124dSJohn Birrell 	 * Validate each part of the CTF header (either V1 or V2).
751d876124dSJohn Birrell 	 * First, we validate the preamble (common to all versions).  At that
752d876124dSJohn Birrell 	 * point, we know specific header version, and can validate the
753d876124dSJohn Birrell 	 * version-specific parts including section offsets and alignments.
754d876124dSJohn Birrell 	 */
755d876124dSJohn Birrell 	if (pp->ctp_magic != CTF_MAGIC)
756d876124dSJohn Birrell 		return (ctf_set_open_errno(errp, ECTF_NOCTFBUF));
757d876124dSJohn Birrell 
758a6fb8691SMark Johnston 	if (pp->ctp_version == CTF_VERSION_2 ||
759a6fb8691SMark Johnston 	    pp->ctp_version == CTF_VERSION_3) {
760d876124dSJohn Birrell 		if (ctfsect->cts_size < sizeof (ctf_header_t))
761d876124dSJohn Birrell 			return (ctf_set_open_errno(errp, ECTF_NOCTFBUF));
762d876124dSJohn Birrell 
763d876124dSJohn Birrell 		bcopy(ctfsect->cts_data, &hp, sizeof (hp));
764d876124dSJohn Birrell 		hdrsz = sizeof (ctf_header_t);
765d876124dSJohn Birrell 
766d876124dSJohn Birrell 	} else
767d876124dSJohn Birrell 		return (ctf_set_open_errno(errp, ECTF_CTFVERS));
768d876124dSJohn Birrell 
769d876124dSJohn Birrell 	size = hp.cth_stroff + hp.cth_strlen;
770d876124dSJohn Birrell 
771d876124dSJohn Birrell 	ctf_dprintf("ctf_bufopen: uncompressed size=%lu\n", (ulong_t)size);
772d876124dSJohn Birrell 
773d876124dSJohn Birrell 	if (hp.cth_lbloff > size || hp.cth_objtoff > size ||
774d876124dSJohn Birrell 	    hp.cth_funcoff > size || hp.cth_typeoff > size ||
775d876124dSJohn Birrell 	    hp.cth_stroff > size)
776d876124dSJohn Birrell 		return (ctf_set_open_errno(errp, ECTF_CORRUPT));
777d876124dSJohn Birrell 
778d876124dSJohn Birrell 	if (hp.cth_lbloff > hp.cth_objtoff ||
779d876124dSJohn Birrell 	    hp.cth_objtoff > hp.cth_funcoff ||
780d876124dSJohn Birrell 	    hp.cth_funcoff > hp.cth_typeoff ||
781d876124dSJohn Birrell 	    hp.cth_typeoff > hp.cth_stroff)
782d876124dSJohn Birrell 		return (ctf_set_open_errno(errp, ECTF_CORRUPT));
783d876124dSJohn Birrell 
784d876124dSJohn Birrell 	if ((hp.cth_lbloff & 3) || (hp.cth_objtoff & 1) ||
785d876124dSJohn Birrell 	    (hp.cth_funcoff & 1) || (hp.cth_typeoff & 3))
786d876124dSJohn Birrell 		return (ctf_set_open_errno(errp, ECTF_CORRUPT));
787d876124dSJohn Birrell 
788d876124dSJohn Birrell 	/*
789d876124dSJohn Birrell 	 * Once everything is determined to be valid, attempt to decompress
790d876124dSJohn Birrell 	 * the CTF data buffer if it is compressed.  Otherwise we just put
791d876124dSJohn Birrell 	 * the data section's buffer pointer into ctf_buf, below.
792d876124dSJohn Birrell 	 */
793d876124dSJohn Birrell 	if (hp.cth_flags & CTF_F_COMPRESS) {
794d876124dSJohn Birrell 		size_t srclen, dstlen;
795d876124dSJohn Birrell 		const void *src;
796d876124dSJohn Birrell 		int rc = Z_OK;
797d876124dSJohn Birrell 
798d876124dSJohn Birrell 		if (ctf_zopen(errp) == NULL)
799d876124dSJohn Birrell 			return (NULL); /* errp is set for us */
800d876124dSJohn Birrell 
801d876124dSJohn Birrell 		if ((base = ctf_data_alloc(size + hdrsz)) == MAP_FAILED)
802d876124dSJohn Birrell 			return (ctf_set_open_errno(errp, ECTF_ZALLOC));
803d876124dSJohn Birrell 
804d876124dSJohn Birrell 		bcopy(ctfsect->cts_data, base, hdrsz);
805d876124dSJohn Birrell 		((ctf_preamble_t *)base)->ctp_flags &= ~CTF_F_COMPRESS;
806d876124dSJohn Birrell 		buf = (uchar_t *)base + hdrsz;
807d876124dSJohn Birrell 
808d876124dSJohn Birrell 		src = (uchar_t *)ctfsect->cts_data + hdrsz;
809d876124dSJohn Birrell 		srclen = ctfsect->cts_size - hdrsz;
810d876124dSJohn Birrell 		dstlen = size;
811d876124dSJohn Birrell 
812d876124dSJohn Birrell 		if ((rc = z_uncompress(buf, &dstlen, src, srclen)) != Z_OK) {
813d876124dSJohn Birrell 			ctf_dprintf("zlib inflate err: %s\n", z_strerror(rc));
814d876124dSJohn Birrell 			ctf_data_free(base, size + hdrsz);
815d876124dSJohn Birrell 			return (ctf_set_open_errno(errp, ECTF_DECOMPRESS));
816d876124dSJohn Birrell 		}
817d876124dSJohn Birrell 
818d876124dSJohn Birrell 		if (dstlen != size) {
819d876124dSJohn Birrell 			ctf_dprintf("zlib inflate short -- got %lu of %lu "
820d876124dSJohn Birrell 			    "bytes\n", (ulong_t)dstlen, (ulong_t)size);
821d876124dSJohn Birrell 			ctf_data_free(base, size + hdrsz);
822d876124dSJohn Birrell 			return (ctf_set_open_errno(errp, ECTF_CORRUPT));
823d876124dSJohn Birrell 		}
824d876124dSJohn Birrell 
825d876124dSJohn Birrell 		ctf_data_protect(base, size + hdrsz);
826d876124dSJohn Birrell 
827d876124dSJohn Birrell 	} else {
828d876124dSJohn Birrell 		base = (void *)ctfsect->cts_data;
829d876124dSJohn Birrell 		buf = (uchar_t *)base + hdrsz;
830d876124dSJohn Birrell 	}
831d876124dSJohn Birrell 
832d876124dSJohn Birrell 	/*
833d876124dSJohn Birrell 	 * Once we have uncompressed and validated the CTF data buffer, we can
834d876124dSJohn Birrell 	 * proceed with allocating a ctf_file_t and initializing it.
835d876124dSJohn Birrell 	 */
836d876124dSJohn Birrell 	if ((fp = ctf_alloc(sizeof (ctf_file_t))) == NULL)
837d876124dSJohn Birrell 		return (ctf_set_open_errno(errp, EAGAIN));
838d876124dSJohn Birrell 
839d876124dSJohn Birrell 	bzero(fp, sizeof (ctf_file_t));
840d876124dSJohn Birrell 	fp->ctf_version = hp.cth_version;
841a6fb8691SMark Johnston 	fp->ctf_idwidth = fp->ctf_version == CTF_VERSION_2 ? 2 : 4;
842d876124dSJohn Birrell 	fp->ctf_fileops = &ctf_fileops[hp.cth_version];
843d876124dSJohn Birrell 	bcopy(ctfsect, &fp->ctf_data, sizeof (ctf_sect_t));
844d876124dSJohn Birrell 
845d876124dSJohn Birrell 	if (symsect != NULL) {
846d876124dSJohn Birrell 		bcopy(symsect, &fp->ctf_symtab, sizeof (ctf_sect_t));
847d876124dSJohn Birrell 		bcopy(strsect, &fp->ctf_strtab, sizeof (ctf_sect_t));
848d876124dSJohn Birrell 	}
849d876124dSJohn Birrell 
850d876124dSJohn Birrell 	if (fp->ctf_data.cts_name != NULL)
851d876124dSJohn Birrell 		fp->ctf_data.cts_name = ctf_strdup(fp->ctf_data.cts_name);
852d876124dSJohn Birrell 	if (fp->ctf_symtab.cts_name != NULL)
853d876124dSJohn Birrell 		fp->ctf_symtab.cts_name = ctf_strdup(fp->ctf_symtab.cts_name);
854d876124dSJohn Birrell 	if (fp->ctf_strtab.cts_name != NULL)
855d876124dSJohn Birrell 		fp->ctf_strtab.cts_name = ctf_strdup(fp->ctf_strtab.cts_name);
856d876124dSJohn Birrell 
857d876124dSJohn Birrell 	if (fp->ctf_data.cts_name == NULL)
858d876124dSJohn Birrell 		fp->ctf_data.cts_name = _CTF_NULLSTR;
859d876124dSJohn Birrell 	if (fp->ctf_symtab.cts_name == NULL)
860d876124dSJohn Birrell 		fp->ctf_symtab.cts_name = _CTF_NULLSTR;
861d876124dSJohn Birrell 	if (fp->ctf_strtab.cts_name == NULL)
862d876124dSJohn Birrell 		fp->ctf_strtab.cts_name = _CTF_NULLSTR;
863d876124dSJohn Birrell 
864d876124dSJohn Birrell 	fp->ctf_str[CTF_STRTAB_0].cts_strs = (const char *)buf + hp.cth_stroff;
865d876124dSJohn Birrell 	fp->ctf_str[CTF_STRTAB_0].cts_len = hp.cth_strlen;
866d876124dSJohn Birrell 
867d876124dSJohn Birrell 	if (strsect != NULL) {
868d876124dSJohn Birrell 		fp->ctf_str[CTF_STRTAB_1].cts_strs = strsect->cts_data;
869d876124dSJohn Birrell 		fp->ctf_str[CTF_STRTAB_1].cts_len = strsect->cts_size;
870d876124dSJohn Birrell 	}
871d876124dSJohn Birrell 
872d876124dSJohn Birrell 	fp->ctf_base = base;
873d876124dSJohn Birrell 	fp->ctf_buf = buf;
874d876124dSJohn Birrell 	fp->ctf_size = size + hdrsz;
875d876124dSJohn Birrell 
876d876124dSJohn Birrell 	/*
877d876124dSJohn Birrell 	 * If we have a parent container name and label, store the relocated
878d876124dSJohn Birrell 	 * string pointers in the CTF container for easy access later.
879d876124dSJohn Birrell 	 */
880d876124dSJohn Birrell 	if (hp.cth_parlabel != 0)
881d876124dSJohn Birrell 		fp->ctf_parlabel = ctf_strptr(fp, hp.cth_parlabel);
882d876124dSJohn Birrell 	if (hp.cth_parname != 0)
883d876124dSJohn Birrell 		fp->ctf_parname = ctf_strptr(fp, hp.cth_parname);
884d876124dSJohn Birrell 
885d876124dSJohn Birrell 	ctf_dprintf("ctf_bufopen: parent name %s (label %s)\n",
886d876124dSJohn Birrell 	    fp->ctf_parname ? fp->ctf_parname : "<NULL>",
887d876124dSJohn Birrell 	    fp->ctf_parlabel ? fp->ctf_parlabel : "<NULL>");
888d876124dSJohn Birrell 
889d876124dSJohn Birrell 	/*
890d876124dSJohn Birrell 	 * If we have a symbol table section, allocate and initialize
891d876124dSJohn Birrell 	 * the symtab translation table, pointed to by ctf_sxlate.
892d876124dSJohn Birrell 	 */
893d876124dSJohn Birrell 	if (symsect != NULL) {
894d876124dSJohn Birrell 		fp->ctf_nsyms = symsect->cts_size / symsect->cts_entsize;
895d876124dSJohn Birrell 		fp->ctf_sxlate = ctf_alloc(fp->ctf_nsyms * sizeof (uint_t));
896d876124dSJohn Birrell 
897d876124dSJohn Birrell 		if (fp->ctf_sxlate == NULL) {
898d876124dSJohn Birrell 			(void) ctf_set_open_errno(errp, EAGAIN);
899d876124dSJohn Birrell 			goto bad;
900d876124dSJohn Birrell 		}
901d876124dSJohn Birrell 
902d876124dSJohn Birrell 		if ((err = init_symtab(fp, &hp, symsect, strsect)) != 0) {
903d876124dSJohn Birrell 			(void) ctf_set_open_errno(errp, err);
904d876124dSJohn Birrell 			goto bad;
905d876124dSJohn Birrell 		}
906d876124dSJohn Birrell 	}
907d876124dSJohn Birrell 
908d876124dSJohn Birrell 	if ((err = init_types(fp, &hp)) != 0) {
909d876124dSJohn Birrell 		(void) ctf_set_open_errno(errp, err);
910d876124dSJohn Birrell 		goto bad;
911d876124dSJohn Birrell 	}
912d876124dSJohn Birrell 
913d876124dSJohn Birrell 	/*
914d876124dSJohn Birrell 	 * Initialize the ctf_lookup_by_name top-level dictionary.  We keep an
915d876124dSJohn Birrell 	 * array of type name prefixes and the corresponding ctf_hash to use.
916d876124dSJohn Birrell 	 * NOTE: This code must be kept in sync with the code in ctf_update().
917d876124dSJohn Birrell 	 */
918d876124dSJohn Birrell 	fp->ctf_lookups[0].ctl_prefix = "struct";
919d876124dSJohn Birrell 	fp->ctf_lookups[0].ctl_len = strlen(fp->ctf_lookups[0].ctl_prefix);
920d876124dSJohn Birrell 	fp->ctf_lookups[0].ctl_hash = &fp->ctf_structs;
921d876124dSJohn Birrell 	fp->ctf_lookups[1].ctl_prefix = "union";
922d876124dSJohn Birrell 	fp->ctf_lookups[1].ctl_len = strlen(fp->ctf_lookups[1].ctl_prefix);
923d876124dSJohn Birrell 	fp->ctf_lookups[1].ctl_hash = &fp->ctf_unions;
924d876124dSJohn Birrell 	fp->ctf_lookups[2].ctl_prefix = "enum";
925d876124dSJohn Birrell 	fp->ctf_lookups[2].ctl_len = strlen(fp->ctf_lookups[2].ctl_prefix);
926d876124dSJohn Birrell 	fp->ctf_lookups[2].ctl_hash = &fp->ctf_enums;
927d876124dSJohn Birrell 	fp->ctf_lookups[3].ctl_prefix = _CTF_NULLSTR;
928d876124dSJohn Birrell 	fp->ctf_lookups[3].ctl_len = strlen(fp->ctf_lookups[3].ctl_prefix);
929d876124dSJohn Birrell 	fp->ctf_lookups[3].ctl_hash = &fp->ctf_names;
930d876124dSJohn Birrell 	fp->ctf_lookups[4].ctl_prefix = NULL;
931d876124dSJohn Birrell 	fp->ctf_lookups[4].ctl_len = 0;
932d876124dSJohn Birrell 	fp->ctf_lookups[4].ctl_hash = NULL;
933d876124dSJohn Birrell 
934d876124dSJohn Birrell 	if (symsect != NULL) {
935d876124dSJohn Birrell 		if (symsect->cts_entsize == sizeof (Elf64_Sym))
936d876124dSJohn Birrell 			(void) ctf_setmodel(fp, CTF_MODEL_LP64);
937d876124dSJohn Birrell 		else
938d876124dSJohn Birrell 			(void) ctf_setmodel(fp, CTF_MODEL_ILP32);
939d876124dSJohn Birrell 	} else
940d876124dSJohn Birrell 		(void) ctf_setmodel(fp, CTF_MODEL_NATIVE);
941d876124dSJohn Birrell 
942d876124dSJohn Birrell 	fp->ctf_refcnt = 1;
943d876124dSJohn Birrell 	return (fp);
944d876124dSJohn Birrell 
945d876124dSJohn Birrell bad:
946d876124dSJohn Birrell 	ctf_close(fp);
947d876124dSJohn Birrell 	return (NULL);
948d876124dSJohn Birrell }
949d876124dSJohn Birrell 
950d876124dSJohn Birrell /*
9518e648814SRui Paulo  * Dupliate a ctf_file_t and its underlying section information into a new
9528e648814SRui Paulo  * container. This works by copying the three ctf_sect_t's of the original
9538e648814SRui Paulo  * container if they exist and passing those into ctf_bufopen. To copy those, we
9548e648814SRui Paulo  * mmap anonymous memory with ctf_data_alloc and bcopy the data across. It's not
9558e648814SRui Paulo  * the cheapest thing, but it's what we've got.
9568e648814SRui Paulo  */
9578e648814SRui Paulo ctf_file_t *
ctf_dup(ctf_file_t * ofp)9588e648814SRui Paulo ctf_dup(ctf_file_t *ofp)
9598e648814SRui Paulo {
9608e648814SRui Paulo 	ctf_file_t *fp;
9618e648814SRui Paulo 	ctf_sect_t ctfsect, symsect, strsect;
9628e648814SRui Paulo 	ctf_sect_t *ctp, *symp, *strp;
9638e648814SRui Paulo 	void *cbuf, *symbuf, *strbuf;
9648e648814SRui Paulo 	int err;
9658e648814SRui Paulo 
9668e648814SRui Paulo 	cbuf = symbuf = strbuf = NULL;
9678e648814SRui Paulo 	/*
9688e648814SRui Paulo 	 * The ctfsect isn't allowed to not exist, but the symbol and string
9698e648814SRui Paulo 	 * section might not. We only need to copy the data of the section, not
9708e648814SRui Paulo 	 * the name, as ctf_bufopen will take care of that.
9718e648814SRui Paulo 	 */
9728e648814SRui Paulo 	bcopy(&ofp->ctf_data, &ctfsect, sizeof (ctf_sect_t));
9738e648814SRui Paulo 	cbuf = ctf_data_alloc(ctfsect.cts_size);
9748e648814SRui Paulo 	if (cbuf == NULL) {
9758e648814SRui Paulo 		(void) ctf_set_errno(ofp, ECTF_MMAP);
9768e648814SRui Paulo 		return (NULL);
9778e648814SRui Paulo 	}
9788e648814SRui Paulo 
9798e648814SRui Paulo 	bcopy(ctfsect.cts_data, cbuf, ctfsect.cts_size);
9808e648814SRui Paulo 	ctf_data_protect(cbuf, ctfsect.cts_size);
9818e648814SRui Paulo 	ctfsect.cts_data = cbuf;
9828e648814SRui Paulo 	ctfsect.cts_offset = 0;
9838e648814SRui Paulo 	ctp = &ctfsect;
9848e648814SRui Paulo 
9858e648814SRui Paulo 	if (ofp->ctf_symtab.cts_data != NULL) {
9868e648814SRui Paulo 		bcopy(&ofp->ctf_symtab, &symsect, sizeof (ctf_sect_t));
9878e648814SRui Paulo 		symbuf = ctf_data_alloc(symsect.cts_size);
9888e648814SRui Paulo 		if (symbuf == NULL) {
9898e648814SRui Paulo 			(void) ctf_set_errno(ofp, ECTF_MMAP);
9908e648814SRui Paulo 			goto err;
9918e648814SRui Paulo 		}
9928e648814SRui Paulo 		bcopy(symsect.cts_data, symbuf, symsect.cts_size);
9938e648814SRui Paulo 		ctf_data_protect(symbuf, symsect.cts_size);
9948e648814SRui Paulo 		symsect.cts_data = symbuf;
9958e648814SRui Paulo 		symsect.cts_offset = 0;
9968e648814SRui Paulo 		symp = &symsect;
9978e648814SRui Paulo 	} else {
9988e648814SRui Paulo 		symp = NULL;
9998e648814SRui Paulo 	}
10008e648814SRui Paulo 
10018e648814SRui Paulo 	if (ofp->ctf_strtab.cts_data != NULL) {
10028e648814SRui Paulo 		bcopy(&ofp->ctf_strtab, &strsect, sizeof (ctf_sect_t));
10038e648814SRui Paulo 		strbuf = ctf_data_alloc(strsect.cts_size);
10048e648814SRui Paulo 		if (strbuf == NULL) {
10058e648814SRui Paulo 			(void) ctf_set_errno(ofp, ECTF_MMAP);
10068e648814SRui Paulo 			goto err;
10078e648814SRui Paulo 		}
10088e648814SRui Paulo 		bcopy(strsect.cts_data, strbuf, strsect.cts_size);
10098e648814SRui Paulo 		ctf_data_protect(strbuf, strsect.cts_size);
10108e648814SRui Paulo 		strsect.cts_data = strbuf;
10118e648814SRui Paulo 		strsect.cts_offset = 0;
10128e648814SRui Paulo 		strp = &strsect;
10138e648814SRui Paulo 	} else {
10148e648814SRui Paulo 		strp = NULL;
10158e648814SRui Paulo 	}
10168e648814SRui Paulo 
10178e648814SRui Paulo 	fp = ctf_bufopen(ctp, symp, strp, &err);
10188e648814SRui Paulo 	if (fp == NULL) {
10198e648814SRui Paulo 		(void) ctf_set_errno(ofp, err);
10208e648814SRui Paulo 		goto err;
10218e648814SRui Paulo 	}
10228e648814SRui Paulo 
10238e648814SRui Paulo 	fp->ctf_flags |= LCTF_MMAP;
10248e648814SRui Paulo 
10258e648814SRui Paulo 	return (fp);
10268e648814SRui Paulo 
10278e648814SRui Paulo err:
10288e648814SRui Paulo 	ctf_data_free(cbuf, ctfsect.cts_size);
10298e648814SRui Paulo 	if (symbuf != NULL)
10308e648814SRui Paulo 		ctf_data_free(symbuf, symsect.cts_size);
10318e648814SRui Paulo 	if (strbuf != NULL)
10328e648814SRui Paulo 		ctf_data_free(strbuf, strsect.cts_size);
10338e648814SRui Paulo 	return (NULL);
10348e648814SRui Paulo }
10358e648814SRui Paulo 
10368e648814SRui Paulo /*
1037d876124dSJohn Birrell  * Close the specified CTF container and free associated data structures.  Note
1038d876124dSJohn Birrell  * that ctf_close() is a reference counted operation: if the specified file is
1039d876124dSJohn Birrell  * the parent of other active containers, its reference count will be greater
1040d876124dSJohn Birrell  * than one and it will be freed later when no active children exist.
1041d876124dSJohn Birrell  */
1042d876124dSJohn Birrell void
ctf_close(ctf_file_t * fp)1043d876124dSJohn Birrell ctf_close(ctf_file_t *fp)
1044d876124dSJohn Birrell {
1045d876124dSJohn Birrell 	ctf_dtdef_t *dtd, *ntd;
1046d876124dSJohn Birrell 
1047d876124dSJohn Birrell 	if (fp == NULL)
1048d876124dSJohn Birrell 		return; /* allow ctf_close(NULL) to simplify caller code */
1049d876124dSJohn Birrell 
1050d876124dSJohn Birrell 	ctf_dprintf("ctf_close(%p) refcnt=%u\n", (void *)fp, fp->ctf_refcnt);
1051d876124dSJohn Birrell 
1052d876124dSJohn Birrell 	if (fp->ctf_refcnt > 1) {
1053d876124dSJohn Birrell 		fp->ctf_refcnt--;
1054d876124dSJohn Birrell 		return;
1055d876124dSJohn Birrell 	}
1056d876124dSJohn Birrell 
1057d876124dSJohn Birrell 	if (fp->ctf_parent != NULL)
1058d876124dSJohn Birrell 		ctf_close(fp->ctf_parent);
1059d876124dSJohn Birrell 
10603f0164abSXin LI 	/*
10613f0164abSXin LI 	 * Note, to work properly with reference counting on the dynamic
10623f0164abSXin LI 	 * section, we must delete the list in reverse.
10633f0164abSXin LI 	 */
10643f0164abSXin LI 	for (dtd = ctf_list_prev(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
10653f0164abSXin LI 		ntd = ctf_list_prev(dtd);
1066d876124dSJohn Birrell 		ctf_dtd_delete(fp, dtd);
1067d876124dSJohn Birrell 	}
1068d876124dSJohn Birrell 
1069d876124dSJohn Birrell 	ctf_free(fp->ctf_dthash, fp->ctf_dthashlen * sizeof (ctf_dtdef_t *));
1070d876124dSJohn Birrell 
1071d876124dSJohn Birrell 	if (fp->ctf_flags & LCTF_MMAP) {
1072d876124dSJohn Birrell 		if (fp->ctf_data.cts_data != NULL)
1073d876124dSJohn Birrell 			ctf_sect_munmap(&fp->ctf_data);
1074d876124dSJohn Birrell 		if (fp->ctf_symtab.cts_data != NULL)
1075d876124dSJohn Birrell 			ctf_sect_munmap(&fp->ctf_symtab);
1076d876124dSJohn Birrell 		if (fp->ctf_strtab.cts_data != NULL)
1077d876124dSJohn Birrell 			ctf_sect_munmap(&fp->ctf_strtab);
1078d876124dSJohn Birrell 	}
1079d876124dSJohn Birrell 
1080d876124dSJohn Birrell 	if (fp->ctf_data.cts_name != _CTF_NULLSTR &&
1081d876124dSJohn Birrell 	    fp->ctf_data.cts_name != NULL) {
1082d876124dSJohn Birrell 		ctf_free((char *)fp->ctf_data.cts_name,
1083d876124dSJohn Birrell 		    strlen(fp->ctf_data.cts_name) + 1);
1084d876124dSJohn Birrell 	}
1085d876124dSJohn Birrell 
1086d876124dSJohn Birrell 	if (fp->ctf_symtab.cts_name != _CTF_NULLSTR &&
1087d876124dSJohn Birrell 	    fp->ctf_symtab.cts_name != NULL) {
1088d876124dSJohn Birrell 		ctf_free((char *)fp->ctf_symtab.cts_name,
1089d876124dSJohn Birrell 		    strlen(fp->ctf_symtab.cts_name) + 1);
1090d876124dSJohn Birrell 	}
1091d876124dSJohn Birrell 
1092d876124dSJohn Birrell 	if (fp->ctf_strtab.cts_name != _CTF_NULLSTR &&
1093d876124dSJohn Birrell 	    fp->ctf_strtab.cts_name != NULL) {
1094d876124dSJohn Birrell 		ctf_free((char *)fp->ctf_strtab.cts_name,
1095d876124dSJohn Birrell 		    strlen(fp->ctf_strtab.cts_name) + 1);
1096d876124dSJohn Birrell 	}
1097d876124dSJohn Birrell 
1098d876124dSJohn Birrell 	if (fp->ctf_base != fp->ctf_data.cts_data && fp->ctf_base != NULL)
1099d876124dSJohn Birrell 		ctf_data_free((void *)fp->ctf_base, fp->ctf_size);
1100d876124dSJohn Birrell 
1101d876124dSJohn Birrell 	if (fp->ctf_sxlate != NULL)
1102d876124dSJohn Birrell 		ctf_free(fp->ctf_sxlate, sizeof (uint_t) * fp->ctf_nsyms);
1103d876124dSJohn Birrell 
1104d876124dSJohn Birrell 	if (fp->ctf_txlate != NULL) {
1105d876124dSJohn Birrell 		ctf_free(fp->ctf_txlate,
1106d876124dSJohn Birrell 		    sizeof (uint_t) * (fp->ctf_typemax + 1));
1107d876124dSJohn Birrell 	}
1108d876124dSJohn Birrell 
1109d876124dSJohn Birrell 	if (fp->ctf_ptrtab != NULL) {
1110d876124dSJohn Birrell 		ctf_free(fp->ctf_ptrtab,
1111a6fb8691SMark Johnston 		    sizeof (uint_t) * (fp->ctf_typemax + 1));
1112d876124dSJohn Birrell 	}
1113d876124dSJohn Birrell 
1114d876124dSJohn Birrell 	ctf_hash_destroy(&fp->ctf_structs);
1115d876124dSJohn Birrell 	ctf_hash_destroy(&fp->ctf_unions);
1116d876124dSJohn Birrell 	ctf_hash_destroy(&fp->ctf_enums);
1117d876124dSJohn Birrell 	ctf_hash_destroy(&fp->ctf_names);
1118d876124dSJohn Birrell 
1119d876124dSJohn Birrell 	ctf_free(fp, sizeof (ctf_file_t));
1120d876124dSJohn Birrell }
1121d876124dSJohn Birrell 
1122d876124dSJohn Birrell /*
1123d876124dSJohn Birrell  * Return the CTF handle for the parent CTF container, if one exists.
1124d876124dSJohn Birrell  * Otherwise return NULL to indicate this container has no imported parent.
1125d876124dSJohn Birrell  */
1126d876124dSJohn Birrell ctf_file_t *
ctf_parent_file(ctf_file_t * fp)1127d876124dSJohn Birrell ctf_parent_file(ctf_file_t *fp)
1128d876124dSJohn Birrell {
1129d876124dSJohn Birrell 	return (fp->ctf_parent);
1130d876124dSJohn Birrell }
1131d876124dSJohn Birrell 
1132d876124dSJohn Birrell /*
1133d876124dSJohn Birrell  * Return the name of the parent CTF container, if one exists.  Otherwise
1134d876124dSJohn Birrell  * return NULL to indicate this container is a root container.
1135d876124dSJohn Birrell  */
1136d876124dSJohn Birrell const char *
ctf_parent_name(ctf_file_t * fp)1137d876124dSJohn Birrell ctf_parent_name(ctf_file_t *fp)
1138d876124dSJohn Birrell {
1139d876124dSJohn Birrell 	return (fp->ctf_parname);
1140d876124dSJohn Birrell }
1141d876124dSJohn Birrell 
1142d876124dSJohn Birrell /*
1143d876124dSJohn Birrell  * Import the types from the specified parent container by storing a pointer
1144d876124dSJohn Birrell  * to it in ctf_parent and incrementing its reference count.  Only one parent
1145d876124dSJohn Birrell  * is allowed: if a parent already exists, it is replaced by the new parent.
1146d876124dSJohn Birrell  */
1147d876124dSJohn Birrell int
ctf_import(ctf_file_t * fp,ctf_file_t * pfp)1148d876124dSJohn Birrell ctf_import(ctf_file_t *fp, ctf_file_t *pfp)
1149d876124dSJohn Birrell {
1150d876124dSJohn Birrell 	if (fp == NULL || fp == pfp || (pfp != NULL && pfp->ctf_refcnt == 0))
1151d876124dSJohn Birrell 		return (ctf_set_errno(fp, EINVAL));
1152d876124dSJohn Birrell 
1153d876124dSJohn Birrell 	if (pfp != NULL && pfp->ctf_dmodel != fp->ctf_dmodel)
1154d876124dSJohn Birrell 		return (ctf_set_errno(fp, ECTF_DMODEL));
1155d876124dSJohn Birrell 
1156d876124dSJohn Birrell 	if (fp->ctf_parent != NULL)
1157d876124dSJohn Birrell 		ctf_close(fp->ctf_parent);
1158d876124dSJohn Birrell 
1159d876124dSJohn Birrell 	if (pfp != NULL) {
1160d876124dSJohn Birrell 		fp->ctf_flags |= LCTF_CHILD;
1161d876124dSJohn Birrell 		pfp->ctf_refcnt++;
1162d876124dSJohn Birrell 	}
1163d876124dSJohn Birrell 
1164d876124dSJohn Birrell 	fp->ctf_parent = pfp;
1165d876124dSJohn Birrell 	return (0);
1166d876124dSJohn Birrell }
1167d876124dSJohn Birrell 
1168d876124dSJohn Birrell /*
1169d876124dSJohn Birrell  * Set the data model constant for the CTF container.
1170d876124dSJohn Birrell  */
1171d876124dSJohn Birrell int
ctf_setmodel(ctf_file_t * fp,int model)1172d876124dSJohn Birrell ctf_setmodel(ctf_file_t *fp, int model)
1173d876124dSJohn Birrell {
1174d876124dSJohn Birrell 	const ctf_dmodel_t *dp;
1175d876124dSJohn Birrell 
1176d876124dSJohn Birrell 	for (dp = _libctf_models; dp->ctd_name != NULL; dp++) {
1177d876124dSJohn Birrell 		if (dp->ctd_code == model) {
1178d876124dSJohn Birrell 			fp->ctf_dmodel = dp;
1179d876124dSJohn Birrell 			return (0);
1180d876124dSJohn Birrell 		}
1181d876124dSJohn Birrell 	}
1182d876124dSJohn Birrell 
1183d876124dSJohn Birrell 	return (ctf_set_errno(fp, EINVAL));
1184d876124dSJohn Birrell }
1185d876124dSJohn Birrell 
1186d876124dSJohn Birrell /*
1187d876124dSJohn Birrell  * Return the data model constant for the CTF container.
1188d876124dSJohn Birrell  */
1189d876124dSJohn Birrell int
ctf_getmodel(ctf_file_t * fp)1190d876124dSJohn Birrell ctf_getmodel(ctf_file_t *fp)
1191d876124dSJohn Birrell {
1192d876124dSJohn Birrell 	return (fp->ctf_dmodel->ctd_code);
1193d876124dSJohn Birrell }
1194d876124dSJohn Birrell 
1195d876124dSJohn Birrell void
ctf_setspecific(ctf_file_t * fp,void * data)1196d876124dSJohn Birrell ctf_setspecific(ctf_file_t *fp, void *data)
1197d876124dSJohn Birrell {
1198d876124dSJohn Birrell 	fp->ctf_specific = data;
1199d876124dSJohn Birrell }
1200d876124dSJohn Birrell 
1201d876124dSJohn Birrell void *
ctf_getspecific(ctf_file_t * fp)1202d876124dSJohn Birrell ctf_getspecific(ctf_file_t *fp)
1203d876124dSJohn Birrell {
1204d876124dSJohn Birrell 	return (fp->ctf_specific);
1205d876124dSJohn Birrell }
1206