xref: /freebsd-src/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c (revision 1673e4046da975ab0e2bf67d45499930ebab0dbe)
1*1673e404SJohn Birrell /*
2*1673e404SJohn Birrell  * CDDL HEADER START
3*1673e404SJohn Birrell  *
4*1673e404SJohn Birrell  * The contents of this file are subject to the terms of the
5*1673e404SJohn Birrell  * Common Development and Distribution License (the "License").
6*1673e404SJohn Birrell  * You may not use this file except in compliance with the License.
7*1673e404SJohn Birrell  *
8*1673e404SJohn Birrell  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*1673e404SJohn Birrell  * or http://www.opensolaris.org/os/licensing.
10*1673e404SJohn Birrell  * See the License for the specific language governing permissions
11*1673e404SJohn Birrell  * and limitations under the License.
12*1673e404SJohn Birrell  *
13*1673e404SJohn Birrell  * When distributing Covered Code, include this CDDL HEADER in each
14*1673e404SJohn Birrell  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*1673e404SJohn Birrell  * If applicable, add the following below this CDDL HEADER, with the
16*1673e404SJohn Birrell  * fields enclosed by brackets "[]" replaced with your own identifying
17*1673e404SJohn Birrell  * information: Portions Copyright [yyyy] [name of copyright owner]
18*1673e404SJohn Birrell  *
19*1673e404SJohn Birrell  * CDDL HEADER END
20*1673e404SJohn Birrell  */
21*1673e404SJohn Birrell /*
22*1673e404SJohn Birrell  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*1673e404SJohn Birrell  * Use is subject to license terms.
24*1673e404SJohn Birrell  */
25*1673e404SJohn Birrell 
26*1673e404SJohn Birrell #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*1673e404SJohn Birrell 
28*1673e404SJohn Birrell /*
29*1673e404SJohn Birrell  * Create and parse buffers containing CTF data.
30*1673e404SJohn Birrell  */
31*1673e404SJohn Birrell 
32*1673e404SJohn Birrell #include <sys/types.h>
33*1673e404SJohn Birrell #include <stdio.h>
34*1673e404SJohn Birrell #include <stdlib.h>
35*1673e404SJohn Birrell #include <strings.h>
36*1673e404SJohn Birrell #include <ctype.h>
37*1673e404SJohn Birrell #include <zlib.h>
38*1673e404SJohn Birrell #include <elf.h>
39*1673e404SJohn Birrell 
40*1673e404SJohn Birrell #include "ctf_headers.h"
41*1673e404SJohn Birrell #include "ctftools.h"
42*1673e404SJohn Birrell #include "strtab.h"
43*1673e404SJohn Birrell #include "memory.h"
44*1673e404SJohn Birrell 
45*1673e404SJohn Birrell /*
46*1673e404SJohn Birrell  * Name of the file currently being read, used to print error messages.  We
47*1673e404SJohn Birrell  * assume that only one file will be read at a time, and thus make no attempt
48*1673e404SJohn Birrell  * to allow curfile to be used simultaneously by multiple threads.
49*1673e404SJohn Birrell  *
50*1673e404SJohn Birrell  * The value is only valid during a call to ctf_load.
51*1673e404SJohn Birrell  */
52*1673e404SJohn Birrell char *curfile;
53*1673e404SJohn Birrell 
54*1673e404SJohn Birrell #define	CTF_BUF_CHUNK_SIZE	(64 * 1024)
55*1673e404SJohn Birrell #define	RES_BUF_CHUNK_SIZE	(64 * 1024)
56*1673e404SJohn Birrell 
57*1673e404SJohn Birrell struct ctf_buf {
58*1673e404SJohn Birrell 	strtab_t ctb_strtab;	/* string table */
59*1673e404SJohn Birrell 	caddr_t ctb_base;	/* pointer to base of buffer */
60*1673e404SJohn Birrell 	caddr_t ctb_end;	/* pointer to end of buffer */
61*1673e404SJohn Birrell 	caddr_t ctb_ptr;	/* pointer to empty buffer space */
62*1673e404SJohn Birrell 	size_t ctb_size;	/* size of buffer */
63*1673e404SJohn Birrell 	int nptent;		/* number of processed types */
64*1673e404SJohn Birrell 	int ntholes;		/* number of type holes */
65*1673e404SJohn Birrell };
66*1673e404SJohn Birrell 
67*1673e404SJohn Birrell /*PRINTFLIKE1*/
68*1673e404SJohn Birrell static void
69*1673e404SJohn Birrell parseterminate(const char *fmt, ...)
70*1673e404SJohn Birrell {
71*1673e404SJohn Birrell 	static char msgbuf[1024]; /* sigh */
72*1673e404SJohn Birrell 	va_list ap;
73*1673e404SJohn Birrell 
74*1673e404SJohn Birrell 	va_start(ap, fmt);
75*1673e404SJohn Birrell 	vsnprintf(msgbuf, sizeof (msgbuf), fmt, ap);
76*1673e404SJohn Birrell 	va_end(ap);
77*1673e404SJohn Birrell 
78*1673e404SJohn Birrell 	terminate("%s: %s\n", curfile, msgbuf);
79*1673e404SJohn Birrell }
80*1673e404SJohn Birrell 
81*1673e404SJohn Birrell static void
82*1673e404SJohn Birrell ctf_buf_grow(ctf_buf_t *b)
83*1673e404SJohn Birrell {
84*1673e404SJohn Birrell 	off_t ptroff = b->ctb_ptr - b->ctb_base;
85*1673e404SJohn Birrell 
86*1673e404SJohn Birrell 	b->ctb_size += CTF_BUF_CHUNK_SIZE;
87*1673e404SJohn Birrell 	b->ctb_base = xrealloc(b->ctb_base, b->ctb_size);
88*1673e404SJohn Birrell 	b->ctb_end = b->ctb_base + b->ctb_size;
89*1673e404SJohn Birrell 	b->ctb_ptr = b->ctb_base + ptroff;
90*1673e404SJohn Birrell }
91*1673e404SJohn Birrell 
92*1673e404SJohn Birrell static ctf_buf_t *
93*1673e404SJohn Birrell ctf_buf_new(void)
94*1673e404SJohn Birrell {
95*1673e404SJohn Birrell 	ctf_buf_t *b = xcalloc(sizeof (ctf_buf_t));
96*1673e404SJohn Birrell 
97*1673e404SJohn Birrell 	strtab_create(&b->ctb_strtab);
98*1673e404SJohn Birrell 	ctf_buf_grow(b);
99*1673e404SJohn Birrell 
100*1673e404SJohn Birrell 	return (b);
101*1673e404SJohn Birrell }
102*1673e404SJohn Birrell 
103*1673e404SJohn Birrell static void
104*1673e404SJohn Birrell ctf_buf_free(ctf_buf_t *b)
105*1673e404SJohn Birrell {
106*1673e404SJohn Birrell 	strtab_destroy(&b->ctb_strtab);
107*1673e404SJohn Birrell 	free(b->ctb_base);
108*1673e404SJohn Birrell 	free(b);
109*1673e404SJohn Birrell }
110*1673e404SJohn Birrell 
111*1673e404SJohn Birrell static uint_t
112*1673e404SJohn Birrell ctf_buf_cur(ctf_buf_t *b)
113*1673e404SJohn Birrell {
114*1673e404SJohn Birrell 	return (b->ctb_ptr - b->ctb_base);
115*1673e404SJohn Birrell }
116*1673e404SJohn Birrell 
117*1673e404SJohn Birrell static void
118*1673e404SJohn Birrell ctf_buf_write(ctf_buf_t *b, void const *p, size_t n)
119*1673e404SJohn Birrell {
120*1673e404SJohn Birrell 	size_t len;
121*1673e404SJohn Birrell 
122*1673e404SJohn Birrell 	while (n != 0) {
123*1673e404SJohn Birrell 		if (b->ctb_ptr == b->ctb_end)
124*1673e404SJohn Birrell 			ctf_buf_grow(b);
125*1673e404SJohn Birrell 
126*1673e404SJohn Birrell 		len = MIN((size_t)(b->ctb_end - b->ctb_ptr), n);
127*1673e404SJohn Birrell 		bcopy(p, b->ctb_ptr, len);
128*1673e404SJohn Birrell 		b->ctb_ptr += len;
129*1673e404SJohn Birrell 
130*1673e404SJohn Birrell 		p = (char const *)p + len;
131*1673e404SJohn Birrell 		n -= len;
132*1673e404SJohn Birrell 	}
133*1673e404SJohn Birrell }
134*1673e404SJohn Birrell 
135*1673e404SJohn Birrell static int
136*1673e404SJohn Birrell write_label(void *arg1, void *arg2)
137*1673e404SJohn Birrell {
138*1673e404SJohn Birrell 	labelent_t *le = arg1;
139*1673e404SJohn Birrell 	ctf_buf_t *b = arg2;
140*1673e404SJohn Birrell 	ctf_lblent_t ctl;
141*1673e404SJohn Birrell 
142*1673e404SJohn Birrell 	ctl.ctl_label = strtab_insert(&b->ctb_strtab, le->le_name);
143*1673e404SJohn Birrell 	ctl.ctl_typeidx = le->le_idx;
144*1673e404SJohn Birrell 
145*1673e404SJohn Birrell 	ctf_buf_write(b, &ctl, sizeof (ctl));
146*1673e404SJohn Birrell 
147*1673e404SJohn Birrell 	return (1);
148*1673e404SJohn Birrell }
149*1673e404SJohn Birrell 
150*1673e404SJohn Birrell static void
151*1673e404SJohn Birrell write_objects(iidesc_t *idp, ctf_buf_t *b)
152*1673e404SJohn Birrell {
153*1673e404SJohn Birrell 	ushort_t id = (idp ? idp->ii_dtype->t_id : 0);
154*1673e404SJohn Birrell 
155*1673e404SJohn Birrell 	ctf_buf_write(b, &id, sizeof (id));
156*1673e404SJohn Birrell 
157*1673e404SJohn Birrell 	debug(3, "Wrote object %s (%d)\n", (idp ? idp->ii_name : "(null)"), id);
158*1673e404SJohn Birrell }
159*1673e404SJohn Birrell 
160*1673e404SJohn Birrell static void
161*1673e404SJohn Birrell write_functions(iidesc_t *idp, ctf_buf_t *b)
162*1673e404SJohn Birrell {
163*1673e404SJohn Birrell 	ushort_t fdata[2];
164*1673e404SJohn Birrell 	ushort_t id;
165*1673e404SJohn Birrell 	int nargs;
166*1673e404SJohn Birrell 	int i;
167*1673e404SJohn Birrell 
168*1673e404SJohn Birrell 	if (!idp) {
169*1673e404SJohn Birrell 		fdata[0] = 0;
170*1673e404SJohn Birrell 		ctf_buf_write(b, &fdata[0], sizeof (fdata[0]));
171*1673e404SJohn Birrell 
172*1673e404SJohn Birrell 		debug(3, "Wrote function (null)\n");
173*1673e404SJohn Birrell 		return;
174*1673e404SJohn Birrell 	}
175*1673e404SJohn Birrell 
176*1673e404SJohn Birrell 	nargs = idp->ii_nargs + (idp->ii_vargs != 0);
177*1673e404SJohn Birrell 	fdata[0] = CTF_TYPE_INFO(CTF_K_FUNCTION, 1, nargs);
178*1673e404SJohn Birrell 	fdata[1] = idp->ii_dtype->t_id;
179*1673e404SJohn Birrell 	ctf_buf_write(b, fdata, sizeof (fdata));
180*1673e404SJohn Birrell 
181*1673e404SJohn Birrell 	for (i = 0; i < idp->ii_nargs; i++) {
182*1673e404SJohn Birrell 		id = idp->ii_args[i]->t_id;
183*1673e404SJohn Birrell 		ctf_buf_write(b, &id, sizeof (id));
184*1673e404SJohn Birrell 	}
185*1673e404SJohn Birrell 
186*1673e404SJohn Birrell 	if (idp->ii_vargs) {
187*1673e404SJohn Birrell 		id = 0;
188*1673e404SJohn Birrell 		ctf_buf_write(b, &id, sizeof (id));
189*1673e404SJohn Birrell 	}
190*1673e404SJohn Birrell 
191*1673e404SJohn Birrell 	debug(3, "Wrote function %s (%d args)\n", idp->ii_name, nargs);
192*1673e404SJohn Birrell }
193*1673e404SJohn Birrell 
194*1673e404SJohn Birrell /*
195*1673e404SJohn Birrell  * Depending on the size of the type being described, either a ctf_stype_t (for
196*1673e404SJohn Birrell  * types with size < CTF_LSTRUCT_THRESH) or a ctf_type_t (all others) will be
197*1673e404SJohn Birrell  * written.  We isolate the determination here so the rest of the writer code
198*1673e404SJohn Birrell  * doesn't need to care.
199*1673e404SJohn Birrell  */
200*1673e404SJohn Birrell static void
201*1673e404SJohn Birrell write_sized_type_rec(ctf_buf_t *b, ctf_type_t *ctt, size_t size)
202*1673e404SJohn Birrell {
203*1673e404SJohn Birrell 	if (size > CTF_MAX_SIZE) {
204*1673e404SJohn Birrell 		ctt->ctt_size = CTF_LSIZE_SENT;
205*1673e404SJohn Birrell 		ctt->ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size);
206*1673e404SJohn Birrell 		ctt->ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size);
207*1673e404SJohn Birrell 		ctf_buf_write(b, ctt, sizeof (*ctt));
208*1673e404SJohn Birrell 	} else {
209*1673e404SJohn Birrell 		ctf_stype_t *cts = (ctf_stype_t *)ctt;
210*1673e404SJohn Birrell 
211*1673e404SJohn Birrell 		cts->ctt_size = (ushort_t)size;
212*1673e404SJohn Birrell 		ctf_buf_write(b, cts, sizeof (*cts));
213*1673e404SJohn Birrell 	}
214*1673e404SJohn Birrell }
215*1673e404SJohn Birrell 
216*1673e404SJohn Birrell static void
217*1673e404SJohn Birrell write_unsized_type_rec(ctf_buf_t *b, ctf_type_t *ctt)
218*1673e404SJohn Birrell {
219*1673e404SJohn Birrell 	ctf_stype_t *cts = (ctf_stype_t *)ctt;
220*1673e404SJohn Birrell 
221*1673e404SJohn Birrell 	ctf_buf_write(b, cts, sizeof (*cts));
222*1673e404SJohn Birrell }
223*1673e404SJohn Birrell 
224*1673e404SJohn Birrell static int
225*1673e404SJohn Birrell write_type(void *arg1, void *arg2)
226*1673e404SJohn Birrell {
227*1673e404SJohn Birrell 	tdesc_t *tp = arg1;
228*1673e404SJohn Birrell 	ctf_buf_t *b = arg2;
229*1673e404SJohn Birrell 	elist_t *ep;
230*1673e404SJohn Birrell 	mlist_t *mp;
231*1673e404SJohn Birrell 	intr_t *ip;
232*1673e404SJohn Birrell 
233*1673e404SJohn Birrell 	size_t offset;
234*1673e404SJohn Birrell 	uint_t encoding;
235*1673e404SJohn Birrell 	uint_t data;
236*1673e404SJohn Birrell 	int isroot = tp->t_flags & TDESC_F_ISROOT;
237*1673e404SJohn Birrell 	int i;
238*1673e404SJohn Birrell 
239*1673e404SJohn Birrell 	ctf_type_t ctt;
240*1673e404SJohn Birrell 	ctf_array_t cta;
241*1673e404SJohn Birrell 	ctf_member_t ctm;
242*1673e404SJohn Birrell 	ctf_lmember_t ctlm;
243*1673e404SJohn Birrell 	ctf_enum_t cte;
244*1673e404SJohn Birrell 	ushort_t id;
245*1673e404SJohn Birrell 
246*1673e404SJohn Birrell 	ctlm.ctlm_pad = 0;
247*1673e404SJohn Birrell 
248*1673e404SJohn Birrell 	/*
249*1673e404SJohn Birrell 	 * There shouldn't be any holes in the type list (where a hole is
250*1673e404SJohn Birrell 	 * defined as two consecutive tdescs without consecutive ids), but
251*1673e404SJohn Birrell 	 * check for them just in case.  If we do find holes, we need to make
252*1673e404SJohn Birrell 	 * fake entries to fill the holes, or we won't be able to reconstruct
253*1673e404SJohn Birrell 	 * the tree from the written data.
254*1673e404SJohn Birrell 	 */
255*1673e404SJohn Birrell 	if (++b->nptent < CTF_TYPE_TO_INDEX(tp->t_id)) {
256*1673e404SJohn Birrell 		debug(2, "genctf: type hole from %d < x < %d\n",
257*1673e404SJohn Birrell 		    b->nptent - 1, CTF_TYPE_TO_INDEX(tp->t_id));
258*1673e404SJohn Birrell 
259*1673e404SJohn Birrell 		ctt.ctt_name = CTF_TYPE_NAME(CTF_STRTAB_0, 0);
260*1673e404SJohn Birrell 		ctt.ctt_info = CTF_TYPE_INFO(0, 0, 0);
261*1673e404SJohn Birrell 		while (b->nptent < CTF_TYPE_TO_INDEX(tp->t_id)) {
262*1673e404SJohn Birrell 			write_sized_type_rec(b, &ctt, 0);
263*1673e404SJohn Birrell 			b->nptent++;
264*1673e404SJohn Birrell 		}
265*1673e404SJohn Birrell 	}
266*1673e404SJohn Birrell 
267*1673e404SJohn Birrell 	offset = strtab_insert(&b->ctb_strtab, tp->t_name);
268*1673e404SJohn Birrell 	ctt.ctt_name = CTF_TYPE_NAME(CTF_STRTAB_0, offset);
269*1673e404SJohn Birrell 
270*1673e404SJohn Birrell 	switch (tp->t_type) {
271*1673e404SJohn Birrell 	case INTRINSIC:
272*1673e404SJohn Birrell 		ip = tp->t_intr;
273*1673e404SJohn Birrell 		if (ip->intr_type == INTR_INT)
274*1673e404SJohn Birrell 			ctt.ctt_info = CTF_TYPE_INFO(CTF_K_INTEGER,
275*1673e404SJohn Birrell 			    isroot, 1);
276*1673e404SJohn Birrell 		else
277*1673e404SJohn Birrell 			ctt.ctt_info = CTF_TYPE_INFO(CTF_K_FLOAT, isroot, 1);
278*1673e404SJohn Birrell 		write_sized_type_rec(b, &ctt, tp->t_size);
279*1673e404SJohn Birrell 
280*1673e404SJohn Birrell 		encoding = 0;
281*1673e404SJohn Birrell 
282*1673e404SJohn Birrell 		if (ip->intr_type == INTR_INT) {
283*1673e404SJohn Birrell 			if (ip->intr_signed)
284*1673e404SJohn Birrell 				encoding |= CTF_INT_SIGNED;
285*1673e404SJohn Birrell 			if (ip->intr_iformat == 'c')
286*1673e404SJohn Birrell 				encoding |= CTF_INT_CHAR;
287*1673e404SJohn Birrell 			else if (ip->intr_iformat == 'b')
288*1673e404SJohn Birrell 				encoding |= CTF_INT_BOOL;
289*1673e404SJohn Birrell 			else if (ip->intr_iformat == 'v')
290*1673e404SJohn Birrell 				encoding |= CTF_INT_VARARGS;
291*1673e404SJohn Birrell 		} else
292*1673e404SJohn Birrell 			encoding = ip->intr_fformat;
293*1673e404SJohn Birrell 
294*1673e404SJohn Birrell 		data = CTF_INT_DATA(encoding, ip->intr_offset, ip->intr_nbits);
295*1673e404SJohn Birrell 		ctf_buf_write(b, &data, sizeof (data));
296*1673e404SJohn Birrell 		break;
297*1673e404SJohn Birrell 
298*1673e404SJohn Birrell 	case POINTER:
299*1673e404SJohn Birrell 		ctt.ctt_info = CTF_TYPE_INFO(CTF_K_POINTER, isroot, 0);
300*1673e404SJohn Birrell 		ctt.ctt_type = tp->t_tdesc->t_id;
301*1673e404SJohn Birrell 		write_unsized_type_rec(b, &ctt);
302*1673e404SJohn Birrell 		break;
303*1673e404SJohn Birrell 
304*1673e404SJohn Birrell 	case ARRAY:
305*1673e404SJohn Birrell 		ctt.ctt_info = CTF_TYPE_INFO(CTF_K_ARRAY, isroot, 1);
306*1673e404SJohn Birrell 		write_sized_type_rec(b, &ctt, tp->t_size);
307*1673e404SJohn Birrell 
308*1673e404SJohn Birrell 		cta.cta_contents = tp->t_ardef->ad_contents->t_id;
309*1673e404SJohn Birrell 		cta.cta_index = tp->t_ardef->ad_idxtype->t_id;
310*1673e404SJohn Birrell 		cta.cta_nelems = tp->t_ardef->ad_nelems;
311*1673e404SJohn Birrell 		ctf_buf_write(b, &cta, sizeof (cta));
312*1673e404SJohn Birrell 		break;
313*1673e404SJohn Birrell 
314*1673e404SJohn Birrell 	case STRUCT:
315*1673e404SJohn Birrell 	case UNION:
316*1673e404SJohn Birrell 		for (i = 0, mp = tp->t_members; mp != NULL; mp = mp->ml_next)
317*1673e404SJohn Birrell 			i++; /* count up struct or union members */
318*1673e404SJohn Birrell 
319*1673e404SJohn Birrell 		if (tp->t_type == STRUCT)
320*1673e404SJohn Birrell 			ctt.ctt_info = CTF_TYPE_INFO(CTF_K_STRUCT, isroot, i);
321*1673e404SJohn Birrell 		else
322*1673e404SJohn Birrell 			ctt.ctt_info = CTF_TYPE_INFO(CTF_K_UNION, isroot, i);
323*1673e404SJohn Birrell 
324*1673e404SJohn Birrell 		write_sized_type_rec(b, &ctt, tp->t_size);
325*1673e404SJohn Birrell 
326*1673e404SJohn Birrell 		if (tp->t_size < CTF_LSTRUCT_THRESH) {
327*1673e404SJohn Birrell 			for (mp = tp->t_members; mp != NULL; mp = mp->ml_next) {
328*1673e404SJohn Birrell 				offset = strtab_insert(&b->ctb_strtab,
329*1673e404SJohn Birrell 				    mp->ml_name);
330*1673e404SJohn Birrell 
331*1673e404SJohn Birrell 				ctm.ctm_name = CTF_TYPE_NAME(CTF_STRTAB_0,
332*1673e404SJohn Birrell 				    offset);
333*1673e404SJohn Birrell 				ctm.ctm_type = mp->ml_type->t_id;
334*1673e404SJohn Birrell 				ctm.ctm_offset = mp->ml_offset;
335*1673e404SJohn Birrell 				ctf_buf_write(b, &ctm, sizeof (ctm));
336*1673e404SJohn Birrell 			}
337*1673e404SJohn Birrell 		} else {
338*1673e404SJohn Birrell 			for (mp = tp->t_members; mp != NULL; mp = mp->ml_next) {
339*1673e404SJohn Birrell 				offset = strtab_insert(&b->ctb_strtab,
340*1673e404SJohn Birrell 				    mp->ml_name);
341*1673e404SJohn Birrell 
342*1673e404SJohn Birrell 				ctlm.ctlm_name = CTF_TYPE_NAME(CTF_STRTAB_0,
343*1673e404SJohn Birrell 				    offset);
344*1673e404SJohn Birrell 				ctlm.ctlm_type = mp->ml_type->t_id;
345*1673e404SJohn Birrell 				ctlm.ctlm_offsethi =
346*1673e404SJohn Birrell 				    CTF_OFFSET_TO_LMEMHI(mp->ml_offset);
347*1673e404SJohn Birrell 				ctlm.ctlm_offsetlo =
348*1673e404SJohn Birrell 				    CTF_OFFSET_TO_LMEMLO(mp->ml_offset);
349*1673e404SJohn Birrell 				ctf_buf_write(b, &ctlm, sizeof (ctlm));
350*1673e404SJohn Birrell 			}
351*1673e404SJohn Birrell 		}
352*1673e404SJohn Birrell 		break;
353*1673e404SJohn Birrell 
354*1673e404SJohn Birrell 	case ENUM:
355*1673e404SJohn Birrell 		for (i = 0, ep = tp->t_emem; ep != NULL; ep = ep->el_next)
356*1673e404SJohn Birrell 			i++; /* count up enum members */
357*1673e404SJohn Birrell 
358*1673e404SJohn Birrell 		ctt.ctt_info = CTF_TYPE_INFO(CTF_K_ENUM, isroot, i);
359*1673e404SJohn Birrell 		write_sized_type_rec(b, &ctt, tp->t_size);
360*1673e404SJohn Birrell 
361*1673e404SJohn Birrell 		for (ep = tp->t_emem; ep != NULL; ep = ep->el_next) {
362*1673e404SJohn Birrell 			offset = strtab_insert(&b->ctb_strtab, ep->el_name);
363*1673e404SJohn Birrell 			cte.cte_name = CTF_TYPE_NAME(CTF_STRTAB_0, offset);
364*1673e404SJohn Birrell 			cte.cte_value = ep->el_number;
365*1673e404SJohn Birrell 			ctf_buf_write(b, &cte, sizeof (cte));
366*1673e404SJohn Birrell 		}
367*1673e404SJohn Birrell 		break;
368*1673e404SJohn Birrell 
369*1673e404SJohn Birrell 	case FORWARD:
370*1673e404SJohn Birrell 		ctt.ctt_info = CTF_TYPE_INFO(CTF_K_FORWARD, isroot, 0);
371*1673e404SJohn Birrell 		ctt.ctt_type = 0;
372*1673e404SJohn Birrell 		write_unsized_type_rec(b, &ctt);
373*1673e404SJohn Birrell 		break;
374*1673e404SJohn Birrell 
375*1673e404SJohn Birrell 	case TYPEDEF:
376*1673e404SJohn Birrell 		ctt.ctt_info = CTF_TYPE_INFO(CTF_K_TYPEDEF, isroot, 0);
377*1673e404SJohn Birrell 		ctt.ctt_type = tp->t_tdesc->t_id;
378*1673e404SJohn Birrell 		write_unsized_type_rec(b, &ctt);
379*1673e404SJohn Birrell 		break;
380*1673e404SJohn Birrell 
381*1673e404SJohn Birrell 	case VOLATILE:
382*1673e404SJohn Birrell 		ctt.ctt_info = CTF_TYPE_INFO(CTF_K_VOLATILE, isroot, 0);
383*1673e404SJohn Birrell 		ctt.ctt_type = tp->t_tdesc->t_id;
384*1673e404SJohn Birrell 		write_unsized_type_rec(b, &ctt);
385*1673e404SJohn Birrell 		break;
386*1673e404SJohn Birrell 
387*1673e404SJohn Birrell 	case CONST:
388*1673e404SJohn Birrell 		ctt.ctt_info = CTF_TYPE_INFO(CTF_K_CONST, isroot, 0);
389*1673e404SJohn Birrell 		ctt.ctt_type = tp->t_tdesc->t_id;
390*1673e404SJohn Birrell 		write_unsized_type_rec(b, &ctt);
391*1673e404SJohn Birrell 		break;
392*1673e404SJohn Birrell 
393*1673e404SJohn Birrell 	case FUNCTION:
394*1673e404SJohn Birrell 		ctt.ctt_info = CTF_TYPE_INFO(CTF_K_FUNCTION, isroot,
395*1673e404SJohn Birrell 		    tp->t_fndef->fn_nargs + tp->t_fndef->fn_vargs);
396*1673e404SJohn Birrell 		ctt.ctt_type = tp->t_fndef->fn_ret->t_id;
397*1673e404SJohn Birrell 		write_unsized_type_rec(b, &ctt);
398*1673e404SJohn Birrell 
399*1673e404SJohn Birrell 		for (i = 0; i < (int) tp->t_fndef->fn_nargs; i++) {
400*1673e404SJohn Birrell 			id = tp->t_fndef->fn_args[i]->t_id;
401*1673e404SJohn Birrell 			ctf_buf_write(b, &id, sizeof (id));
402*1673e404SJohn Birrell 		}
403*1673e404SJohn Birrell 
404*1673e404SJohn Birrell 		if (tp->t_fndef->fn_vargs) {
405*1673e404SJohn Birrell 			id = 0;
406*1673e404SJohn Birrell 			ctf_buf_write(b, &id, sizeof (id));
407*1673e404SJohn Birrell 			i++;
408*1673e404SJohn Birrell 		}
409*1673e404SJohn Birrell 
410*1673e404SJohn Birrell 		if (i & 1) {
411*1673e404SJohn Birrell 			id = 0;
412*1673e404SJohn Birrell 			ctf_buf_write(b, &id, sizeof (id));
413*1673e404SJohn Birrell 		}
414*1673e404SJohn Birrell 		break;
415*1673e404SJohn Birrell 
416*1673e404SJohn Birrell 	case RESTRICT:
417*1673e404SJohn Birrell 		ctt.ctt_info = CTF_TYPE_INFO(CTF_K_RESTRICT, isroot, 0);
418*1673e404SJohn Birrell 		ctt.ctt_type = tp->t_tdesc->t_id;
419*1673e404SJohn Birrell 		write_unsized_type_rec(b, &ctt);
420*1673e404SJohn Birrell 		break;
421*1673e404SJohn Birrell 
422*1673e404SJohn Birrell 	default:
423*1673e404SJohn Birrell 		warning("Can't write unknown type %d\n", tp->t_type);
424*1673e404SJohn Birrell 	}
425*1673e404SJohn Birrell 
426*1673e404SJohn Birrell 	debug(3, "Wrote type %d %s\n", tp->t_id, tdesc_name(tp));
427*1673e404SJohn Birrell 
428*1673e404SJohn Birrell 	return (1);
429*1673e404SJohn Birrell }
430*1673e404SJohn Birrell 
431*1673e404SJohn Birrell typedef struct resbuf {
432*1673e404SJohn Birrell 	caddr_t rb_base;
433*1673e404SJohn Birrell 	caddr_t rb_ptr;
434*1673e404SJohn Birrell 	size_t rb_size;
435*1673e404SJohn Birrell 	z_stream rb_zstr;
436*1673e404SJohn Birrell } resbuf_t;
437*1673e404SJohn Birrell 
438*1673e404SJohn Birrell static void
439*1673e404SJohn Birrell rbzs_grow(resbuf_t *rb)
440*1673e404SJohn Birrell {
441*1673e404SJohn Birrell 	off_t ptroff = (caddr_t)rb->rb_zstr.next_out - rb->rb_base;
442*1673e404SJohn Birrell 
443*1673e404SJohn Birrell 	rb->rb_size += RES_BUF_CHUNK_SIZE;
444*1673e404SJohn Birrell 	rb->rb_base = xrealloc(rb->rb_base, rb->rb_size);
445*1673e404SJohn Birrell 	rb->rb_ptr = rb->rb_base + ptroff;
446*1673e404SJohn Birrell 	rb->rb_zstr.next_out = (Bytef *)(rb->rb_ptr);
447*1673e404SJohn Birrell 	rb->rb_zstr.avail_out += RES_BUF_CHUNK_SIZE;
448*1673e404SJohn Birrell }
449*1673e404SJohn Birrell 
450*1673e404SJohn Birrell static void
451*1673e404SJohn Birrell compress_start(resbuf_t *rb)
452*1673e404SJohn Birrell {
453*1673e404SJohn Birrell 	int rc;
454*1673e404SJohn Birrell 
455*1673e404SJohn Birrell 	rb->rb_zstr.zalloc = (alloc_func)0;
456*1673e404SJohn Birrell 	rb->rb_zstr.zfree = (free_func)0;
457*1673e404SJohn Birrell 	rb->rb_zstr.opaque = (voidpf)0;
458*1673e404SJohn Birrell 
459*1673e404SJohn Birrell 	if ((rc = deflateInit(&rb->rb_zstr, Z_BEST_COMPRESSION)) != Z_OK)
460*1673e404SJohn Birrell 		parseterminate("zlib start failed: %s", zError(rc));
461*1673e404SJohn Birrell }
462*1673e404SJohn Birrell 
463*1673e404SJohn Birrell static ssize_t
464*1673e404SJohn Birrell compress_buffer(void *buf, size_t n, void *data)
465*1673e404SJohn Birrell {
466*1673e404SJohn Birrell 	resbuf_t *rb = (resbuf_t *)data;
467*1673e404SJohn Birrell 	int rc;
468*1673e404SJohn Birrell 
469*1673e404SJohn Birrell 	rb->rb_zstr.next_out = (Bytef *)rb->rb_ptr;
470*1673e404SJohn Birrell 	rb->rb_zstr.avail_out = rb->rb_size - (rb->rb_ptr - rb->rb_base);
471*1673e404SJohn Birrell 	rb->rb_zstr.next_in = buf;
472*1673e404SJohn Birrell 	rb->rb_zstr.avail_in = n;
473*1673e404SJohn Birrell 
474*1673e404SJohn Birrell 	while (rb->rb_zstr.avail_in) {
475*1673e404SJohn Birrell 		if (rb->rb_zstr.avail_out == 0)
476*1673e404SJohn Birrell 			rbzs_grow(rb);
477*1673e404SJohn Birrell 
478*1673e404SJohn Birrell 		if ((rc = deflate(&rb->rb_zstr, Z_NO_FLUSH)) != Z_OK)
479*1673e404SJohn Birrell 			parseterminate("zlib deflate failed: %s", zError(rc));
480*1673e404SJohn Birrell 	}
481*1673e404SJohn Birrell 	rb->rb_ptr = (caddr_t)rb->rb_zstr.next_out;
482*1673e404SJohn Birrell 
483*1673e404SJohn Birrell 	return (n);
484*1673e404SJohn Birrell }
485*1673e404SJohn Birrell 
486*1673e404SJohn Birrell static void
487*1673e404SJohn Birrell compress_flush(resbuf_t *rb, int type)
488*1673e404SJohn Birrell {
489*1673e404SJohn Birrell 	int rc;
490*1673e404SJohn Birrell 
491*1673e404SJohn Birrell 	for (;;) {
492*1673e404SJohn Birrell 		if (rb->rb_zstr.avail_out == 0)
493*1673e404SJohn Birrell 			rbzs_grow(rb);
494*1673e404SJohn Birrell 
495*1673e404SJohn Birrell 		rc = deflate(&rb->rb_zstr, type);
496*1673e404SJohn Birrell 		if ((type == Z_FULL_FLUSH && rc == Z_BUF_ERROR) ||
497*1673e404SJohn Birrell 		    (type == Z_FINISH && rc == Z_STREAM_END))
498*1673e404SJohn Birrell 			break;
499*1673e404SJohn Birrell 		else if (rc != Z_OK)
500*1673e404SJohn Birrell 			parseterminate("zlib finish failed: %s", zError(rc));
501*1673e404SJohn Birrell 	}
502*1673e404SJohn Birrell 	rb->rb_ptr = (caddr_t)rb->rb_zstr.next_out;
503*1673e404SJohn Birrell }
504*1673e404SJohn Birrell 
505*1673e404SJohn Birrell static void
506*1673e404SJohn Birrell compress_end(resbuf_t *rb)
507*1673e404SJohn Birrell {
508*1673e404SJohn Birrell 	int rc;
509*1673e404SJohn Birrell 
510*1673e404SJohn Birrell 	compress_flush(rb, Z_FINISH);
511*1673e404SJohn Birrell 
512*1673e404SJohn Birrell 	if ((rc = deflateEnd(&rb->rb_zstr)) != Z_OK)
513*1673e404SJohn Birrell 		parseterminate("zlib end failed: %s", zError(rc));
514*1673e404SJohn Birrell }
515*1673e404SJohn Birrell 
516*1673e404SJohn Birrell /*
517*1673e404SJohn Birrell  * Pad the buffer to a power-of-2 boundary
518*1673e404SJohn Birrell  */
519*1673e404SJohn Birrell static void
520*1673e404SJohn Birrell pad_buffer(ctf_buf_t *buf, int align)
521*1673e404SJohn Birrell {
522*1673e404SJohn Birrell 	uint_t cur = ctf_buf_cur(buf);
523*1673e404SJohn Birrell 	ssize_t topad = (align - (cur % align)) % align;
524*1673e404SJohn Birrell 	static const char pad[8] = { 0 };
525*1673e404SJohn Birrell 
526*1673e404SJohn Birrell 	while (topad > 0) {
527*1673e404SJohn Birrell 		ctf_buf_write(buf, pad, (topad > 8 ? 8 : topad));
528*1673e404SJohn Birrell 		topad -= 8;
529*1673e404SJohn Birrell 	}
530*1673e404SJohn Birrell }
531*1673e404SJohn Birrell 
532*1673e404SJohn Birrell static ssize_t
533*1673e404SJohn Birrell bcopy_data(void *buf, size_t n, void *data)
534*1673e404SJohn Birrell {
535*1673e404SJohn Birrell 	caddr_t *posp = (caddr_t *)data;
536*1673e404SJohn Birrell 	bcopy(buf, *posp, n);
537*1673e404SJohn Birrell 	*posp += n;
538*1673e404SJohn Birrell 	return (n);
539*1673e404SJohn Birrell }
540*1673e404SJohn Birrell 
541*1673e404SJohn Birrell static caddr_t
542*1673e404SJohn Birrell write_buffer(ctf_header_t *h, ctf_buf_t *buf, size_t *resszp)
543*1673e404SJohn Birrell {
544*1673e404SJohn Birrell 	caddr_t outbuf;
545*1673e404SJohn Birrell 	caddr_t bufpos;
546*1673e404SJohn Birrell 
547*1673e404SJohn Birrell 	outbuf = xmalloc(sizeof (ctf_header_t) + (buf->ctb_ptr - buf->ctb_base)
548*1673e404SJohn Birrell 	    + buf->ctb_strtab.str_size);
549*1673e404SJohn Birrell 
550*1673e404SJohn Birrell 	bufpos = outbuf;
551*1673e404SJohn Birrell 	(void) bcopy_data(h, sizeof (ctf_header_t), &bufpos);
552*1673e404SJohn Birrell 	(void) bcopy_data(buf->ctb_base, buf->ctb_ptr - buf->ctb_base,
553*1673e404SJohn Birrell 	    &bufpos);
554*1673e404SJohn Birrell 	(void) strtab_write(&buf->ctb_strtab, bcopy_data, &bufpos);
555*1673e404SJohn Birrell 	*resszp = bufpos - outbuf;
556*1673e404SJohn Birrell 	return (outbuf);
557*1673e404SJohn Birrell }
558*1673e404SJohn Birrell 
559*1673e404SJohn Birrell /*
560*1673e404SJohn Birrell  * Create the compression buffer, and fill it with the CTF and string
561*1673e404SJohn Birrell  * table data.  We flush the compression state between the two so the
562*1673e404SJohn Birrell  * dictionary used for the string tables won't be polluted with values
563*1673e404SJohn Birrell  * that made sense for the CTF data.
564*1673e404SJohn Birrell  */
565*1673e404SJohn Birrell static caddr_t
566*1673e404SJohn Birrell write_compressed_buffer(ctf_header_t *h, ctf_buf_t *buf, size_t *resszp)
567*1673e404SJohn Birrell {
568*1673e404SJohn Birrell 	resbuf_t resbuf;
569*1673e404SJohn Birrell 	resbuf.rb_size = RES_BUF_CHUNK_SIZE;
570*1673e404SJohn Birrell 	resbuf.rb_base = xmalloc(resbuf.rb_size);
571*1673e404SJohn Birrell 	bcopy(h, resbuf.rb_base, sizeof (ctf_header_t));
572*1673e404SJohn Birrell 	resbuf.rb_ptr = resbuf.rb_base + sizeof (ctf_header_t);
573*1673e404SJohn Birrell 
574*1673e404SJohn Birrell 	compress_start(&resbuf);
575*1673e404SJohn Birrell 	(void) compress_buffer(buf->ctb_base, buf->ctb_ptr - buf->ctb_base,
576*1673e404SJohn Birrell 	    &resbuf);
577*1673e404SJohn Birrell 	compress_flush(&resbuf, Z_FULL_FLUSH);
578*1673e404SJohn Birrell 	(void) strtab_write(&buf->ctb_strtab, compress_buffer, &resbuf);
579*1673e404SJohn Birrell 	compress_end(&resbuf);
580*1673e404SJohn Birrell 
581*1673e404SJohn Birrell 	*resszp = (resbuf.rb_ptr - resbuf.rb_base);
582*1673e404SJohn Birrell 	return (resbuf.rb_base);
583*1673e404SJohn Birrell }
584*1673e404SJohn Birrell 
585*1673e404SJohn Birrell caddr_t
586*1673e404SJohn Birrell ctf_gen(iiburst_t *iiburst, size_t *resszp, int do_compress)
587*1673e404SJohn Birrell {
588*1673e404SJohn Birrell 	ctf_buf_t *buf = ctf_buf_new();
589*1673e404SJohn Birrell 	ctf_header_t h;
590*1673e404SJohn Birrell 	caddr_t outbuf;
591*1673e404SJohn Birrell 
592*1673e404SJohn Birrell 	int i;
593*1673e404SJohn Birrell 
594*1673e404SJohn Birrell 	/*
595*1673e404SJohn Birrell 	 * Prepare the header, and create the CTF output buffers.  The data
596*1673e404SJohn Birrell 	 * object section and function section are both lists of 2-byte
597*1673e404SJohn Birrell 	 * integers; we pad these out to the next 4-byte boundary if needed.
598*1673e404SJohn Birrell 	 */
599*1673e404SJohn Birrell 	h.cth_magic = CTF_MAGIC;
600*1673e404SJohn Birrell 	h.cth_version = CTF_VERSION;
601*1673e404SJohn Birrell 	h.cth_flags = do_compress ? CTF_F_COMPRESS : 0;
602*1673e404SJohn Birrell 	h.cth_parlabel = strtab_insert(&buf->ctb_strtab,
603*1673e404SJohn Birrell 	    iiburst->iib_td->td_parlabel);
604*1673e404SJohn Birrell 	h.cth_parname = strtab_insert(&buf->ctb_strtab,
605*1673e404SJohn Birrell 	    iiburst->iib_td->td_parname);
606*1673e404SJohn Birrell 
607*1673e404SJohn Birrell 	h.cth_lbloff = 0;
608*1673e404SJohn Birrell 	(void) list_iter(iiburst->iib_td->td_labels, write_label,
609*1673e404SJohn Birrell 	    buf);
610*1673e404SJohn Birrell 
611*1673e404SJohn Birrell 	pad_buffer(buf, 2);
612*1673e404SJohn Birrell 	h.cth_objtoff = ctf_buf_cur(buf);
613*1673e404SJohn Birrell 	for (i = 0; i < iiburst->iib_nobjts; i++)
614*1673e404SJohn Birrell 		write_objects(iiburst->iib_objts[i], buf);
615*1673e404SJohn Birrell 
616*1673e404SJohn Birrell 	pad_buffer(buf, 2);
617*1673e404SJohn Birrell 	h.cth_funcoff = ctf_buf_cur(buf);
618*1673e404SJohn Birrell 	for (i = 0; i < iiburst->iib_nfuncs; i++)
619*1673e404SJohn Birrell 		write_functions(iiburst->iib_funcs[i], buf);
620*1673e404SJohn Birrell 
621*1673e404SJohn Birrell 	pad_buffer(buf, 4);
622*1673e404SJohn Birrell 	h.cth_typeoff = ctf_buf_cur(buf);
623*1673e404SJohn Birrell 	(void) list_iter(iiburst->iib_types, write_type, buf);
624*1673e404SJohn Birrell 
625*1673e404SJohn Birrell 	debug(2, "CTF wrote %d types\n", list_count(iiburst->iib_types));
626*1673e404SJohn Birrell 
627*1673e404SJohn Birrell 	h.cth_stroff = ctf_buf_cur(buf);
628*1673e404SJohn Birrell 	h.cth_strlen = strtab_size(&buf->ctb_strtab);
629*1673e404SJohn Birrell 
630*1673e404SJohn Birrell 	/*
631*1673e404SJohn Birrell 	 * We only do compression for ctfmerge, as ctfconvert is only
632*1673e404SJohn Birrell 	 * supposed to be used on intermediary build objects. This is
633*1673e404SJohn Birrell 	 * significantly faster.
634*1673e404SJohn Birrell 	 */
635*1673e404SJohn Birrell 	if (do_compress)
636*1673e404SJohn Birrell 		outbuf = write_compressed_buffer(&h, buf, resszp);
637*1673e404SJohn Birrell 	else
638*1673e404SJohn Birrell 		outbuf = write_buffer(&h, buf, resszp);
639*1673e404SJohn Birrell 
640*1673e404SJohn Birrell 	ctf_buf_free(buf);
641*1673e404SJohn Birrell 	return (outbuf);
642*1673e404SJohn Birrell }
643*1673e404SJohn Birrell 
644*1673e404SJohn Birrell static void
645*1673e404SJohn Birrell get_ctt_size(ctf_type_t *ctt, size_t *sizep, size_t *incrementp)
646*1673e404SJohn Birrell {
647*1673e404SJohn Birrell 	if (ctt->ctt_size == CTF_LSIZE_SENT) {
648*1673e404SJohn Birrell 		*sizep = (size_t)CTF_TYPE_LSIZE(ctt);
649*1673e404SJohn Birrell 		*incrementp = sizeof (ctf_type_t);
650*1673e404SJohn Birrell 	} else {
651*1673e404SJohn Birrell 		*sizep = ctt->ctt_size;
652*1673e404SJohn Birrell 		*incrementp = sizeof (ctf_stype_t);
653*1673e404SJohn Birrell 	}
654*1673e404SJohn Birrell }
655*1673e404SJohn Birrell 
656*1673e404SJohn Birrell static int
657*1673e404SJohn Birrell count_types(ctf_header_t *h, caddr_t data)
658*1673e404SJohn Birrell {
659*1673e404SJohn Birrell 	caddr_t dptr = data + h->cth_typeoff;
660*1673e404SJohn Birrell 	int count = 0;
661*1673e404SJohn Birrell 
662*1673e404SJohn Birrell 	dptr = data + h->cth_typeoff;
663*1673e404SJohn Birrell 	while (dptr < data + h->cth_stroff) {
664*1673e404SJohn Birrell 		void *v = (void *) dptr;
665*1673e404SJohn Birrell 		ctf_type_t *ctt = v;
666*1673e404SJohn Birrell 		size_t vlen = CTF_INFO_VLEN(ctt->ctt_info);
667*1673e404SJohn Birrell 		size_t size, increment;
668*1673e404SJohn Birrell 
669*1673e404SJohn Birrell 		get_ctt_size(ctt, &size, &increment);
670*1673e404SJohn Birrell 
671*1673e404SJohn Birrell 		switch (CTF_INFO_KIND(ctt->ctt_info)) {
672*1673e404SJohn Birrell 		case CTF_K_INTEGER:
673*1673e404SJohn Birrell 		case CTF_K_FLOAT:
674*1673e404SJohn Birrell 			dptr += 4;
675*1673e404SJohn Birrell 			break;
676*1673e404SJohn Birrell 		case CTF_K_POINTER:
677*1673e404SJohn Birrell 		case CTF_K_FORWARD:
678*1673e404SJohn Birrell 		case CTF_K_TYPEDEF:
679*1673e404SJohn Birrell 		case CTF_K_VOLATILE:
680*1673e404SJohn Birrell 		case CTF_K_CONST:
681*1673e404SJohn Birrell 		case CTF_K_RESTRICT:
682*1673e404SJohn Birrell 		case CTF_K_FUNCTION:
683*1673e404SJohn Birrell 			dptr += sizeof (ushort_t) * (vlen + (vlen & 1));
684*1673e404SJohn Birrell 			break;
685*1673e404SJohn Birrell 		case CTF_K_ARRAY:
686*1673e404SJohn Birrell 			dptr += sizeof (ctf_array_t);
687*1673e404SJohn Birrell 			break;
688*1673e404SJohn Birrell 		case CTF_K_STRUCT:
689*1673e404SJohn Birrell 		case CTF_K_UNION:
690*1673e404SJohn Birrell 			if (size < CTF_LSTRUCT_THRESH)
691*1673e404SJohn Birrell 				dptr += sizeof (ctf_member_t) * vlen;
692*1673e404SJohn Birrell 			else
693*1673e404SJohn Birrell 				dptr += sizeof (ctf_lmember_t) * vlen;
694*1673e404SJohn Birrell 			break;
695*1673e404SJohn Birrell 		case CTF_K_ENUM:
696*1673e404SJohn Birrell 			dptr += sizeof (ctf_enum_t) * vlen;
697*1673e404SJohn Birrell 			break;
698*1673e404SJohn Birrell 		case CTF_K_UNKNOWN:
699*1673e404SJohn Birrell 			break;
700*1673e404SJohn Birrell 		default:
701*1673e404SJohn Birrell 			parseterminate("Unknown CTF type %d (#%d) at %#x",
702*1673e404SJohn Birrell 			    CTF_INFO_KIND(ctt->ctt_info), count, dptr - data);
703*1673e404SJohn Birrell 		}
704*1673e404SJohn Birrell 
705*1673e404SJohn Birrell 		dptr += increment;
706*1673e404SJohn Birrell 		count++;
707*1673e404SJohn Birrell 	}
708*1673e404SJohn Birrell 
709*1673e404SJohn Birrell 	debug(3, "CTF read %d types\n", count);
710*1673e404SJohn Birrell 
711*1673e404SJohn Birrell 	return (count);
712*1673e404SJohn Birrell }
713*1673e404SJohn Birrell 
714*1673e404SJohn Birrell /*
715*1673e404SJohn Birrell  * Resurrect the labels stored in the CTF data, returning the index associated
716*1673e404SJohn Birrell  * with a label provided by the caller.  There are several cases, outlined
717*1673e404SJohn Birrell  * below.  Note that, given two labels, the one associated with the lesser type
718*1673e404SJohn Birrell  * index is considered to be older than the other.
719*1673e404SJohn Birrell  *
720*1673e404SJohn Birrell  *  1. matchlbl == NULL - return the index of the most recent label.
721*1673e404SJohn Birrell  *  2. matchlbl == "BASE" - return the index of the oldest label.
722*1673e404SJohn Birrell  *  3. matchlbl != NULL, but doesn't match any labels in the section - warn
723*1673e404SJohn Birrell  *	the user, and proceed as if matchlbl == "BASE" (for safety).
724*1673e404SJohn Birrell  *  4. matchlbl != NULL, and matches one of the labels in the section - return
725*1673e404SJohn Birrell  *	the type index associated with the label.
726*1673e404SJohn Birrell  */
727*1673e404SJohn Birrell static int
728*1673e404SJohn Birrell resurrect_labels(ctf_header_t *h, tdata_t *td, caddr_t ctfdata, char *matchlbl)
729*1673e404SJohn Birrell {
730*1673e404SJohn Birrell 	caddr_t buf = ctfdata + h->cth_lbloff;
731*1673e404SJohn Birrell 	caddr_t sbuf = ctfdata + h->cth_stroff;
732*1673e404SJohn Birrell 	size_t bufsz = h->cth_objtoff - h->cth_lbloff;
733*1673e404SJohn Birrell 	int lastidx = 0, baseidx = -1;
734*1673e404SJohn Birrell 	char *baselabel = NULL;
735*1673e404SJohn Birrell 	ctf_lblent_t *ctl;
736*1673e404SJohn Birrell 	void *v = (void *) buf;
737*1673e404SJohn Birrell 
738*1673e404SJohn Birrell 	for (ctl = v; (caddr_t)ctl < buf + bufsz; ctl++) {
739*1673e404SJohn Birrell 		char *label = sbuf + ctl->ctl_label;
740*1673e404SJohn Birrell 
741*1673e404SJohn Birrell 		lastidx = ctl->ctl_typeidx;
742*1673e404SJohn Birrell 
743*1673e404SJohn Birrell 		debug(3, "Resurrected label %s type idx %d\n", label, lastidx);
744*1673e404SJohn Birrell 
745*1673e404SJohn Birrell 		tdata_label_add(td, label, lastidx);
746*1673e404SJohn Birrell 
747*1673e404SJohn Birrell 		if (baseidx == -1) {
748*1673e404SJohn Birrell 			baseidx = lastidx;
749*1673e404SJohn Birrell 			baselabel = label;
750*1673e404SJohn Birrell 			if (matchlbl != NULL && streq(matchlbl, "BASE"))
751*1673e404SJohn Birrell 				return (lastidx);
752*1673e404SJohn Birrell 		}
753*1673e404SJohn Birrell 
754*1673e404SJohn Birrell 		if (matchlbl != NULL && streq(label, matchlbl))
755*1673e404SJohn Birrell 			return (lastidx);
756*1673e404SJohn Birrell 	}
757*1673e404SJohn Birrell 
758*1673e404SJohn Birrell 	if (matchlbl != NULL) {
759*1673e404SJohn Birrell 		/* User provided a label that didn't match */
760*1673e404SJohn Birrell 		warning("%s: Cannot find label `%s' - using base (%s)\n",
761*1673e404SJohn Birrell 		    curfile, matchlbl, (baselabel ? baselabel : "NONE"));
762*1673e404SJohn Birrell 
763*1673e404SJohn Birrell 		tdata_label_free(td);
764*1673e404SJohn Birrell 		tdata_label_add(td, baselabel, baseidx);
765*1673e404SJohn Birrell 
766*1673e404SJohn Birrell 		return (baseidx);
767*1673e404SJohn Birrell 	}
768*1673e404SJohn Birrell 
769*1673e404SJohn Birrell 	return (lastidx);
770*1673e404SJohn Birrell }
771*1673e404SJohn Birrell 
772*1673e404SJohn Birrell static void
773*1673e404SJohn Birrell resurrect_objects(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
774*1673e404SJohn Birrell     caddr_t ctfdata, symit_data_t *si)
775*1673e404SJohn Birrell {
776*1673e404SJohn Birrell 	caddr_t buf = ctfdata + h->cth_objtoff;
777*1673e404SJohn Birrell 	size_t bufsz = h->cth_funcoff - h->cth_objtoff;
778*1673e404SJohn Birrell 	caddr_t dptr;
779*1673e404SJohn Birrell 
780*1673e404SJohn Birrell 	symit_reset(si);
781*1673e404SJohn Birrell 	for (dptr = buf; dptr < buf + bufsz; dptr += 2) {
782*1673e404SJohn Birrell 		void *v = (void *) dptr;
783*1673e404SJohn Birrell 		ushort_t id = *((ushort_t *)v);
784*1673e404SJohn Birrell 		iidesc_t *ii;
785*1673e404SJohn Birrell 		GElf_Sym *sym;
786*1673e404SJohn Birrell 
787*1673e404SJohn Birrell 		if (!(sym = symit_next(si, STT_OBJECT)) && id != 0) {
788*1673e404SJohn Birrell 			parseterminate(
789*1673e404SJohn Birrell 			    "Unexpected end of object symbols at %x of %x",
790*1673e404SJohn Birrell 			    dptr - buf, bufsz);
791*1673e404SJohn Birrell 		}
792*1673e404SJohn Birrell 
793*1673e404SJohn Birrell 		if (id == 0) {
794*1673e404SJohn Birrell 			debug(3, "Skipping null object\n");
795*1673e404SJohn Birrell 			continue;
796*1673e404SJohn Birrell 		} else if (id >= tdsize) {
797*1673e404SJohn Birrell 			parseterminate("Reference to invalid type %d", id);
798*1673e404SJohn Birrell 		}
799*1673e404SJohn Birrell 
800*1673e404SJohn Birrell 		ii = iidesc_new(symit_name(si));
801*1673e404SJohn Birrell 		ii->ii_dtype = tdarr[id];
802*1673e404SJohn Birrell 		if (GELF_ST_BIND(sym->st_info) == STB_LOCAL) {
803*1673e404SJohn Birrell 			ii->ii_type = II_SVAR;
804*1673e404SJohn Birrell 			ii->ii_owner = xstrdup(symit_curfile(si));
805*1673e404SJohn Birrell 		} else
806*1673e404SJohn Birrell 			ii->ii_type = II_GVAR;
807*1673e404SJohn Birrell 		hash_add(td->td_iihash, ii);
808*1673e404SJohn Birrell 
809*1673e404SJohn Birrell 		debug(3, "Resurrected %s object %s (%d) from %s\n",
810*1673e404SJohn Birrell 		    (ii->ii_type == II_GVAR ? "global" : "static"),
811*1673e404SJohn Birrell 		    ii->ii_name, id, (ii->ii_owner ? ii->ii_owner : "(none)"));
812*1673e404SJohn Birrell 	}
813*1673e404SJohn Birrell }
814*1673e404SJohn Birrell 
815*1673e404SJohn Birrell static void
816*1673e404SJohn Birrell resurrect_functions(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
817*1673e404SJohn Birrell     caddr_t ctfdata, symit_data_t *si)
818*1673e404SJohn Birrell {
819*1673e404SJohn Birrell 	caddr_t buf = ctfdata + h->cth_funcoff;
820*1673e404SJohn Birrell 	size_t bufsz = h->cth_typeoff - h->cth_funcoff;
821*1673e404SJohn Birrell 	caddr_t dptr = buf;
822*1673e404SJohn Birrell 	iidesc_t *ii;
823*1673e404SJohn Birrell 	ushort_t info;
824*1673e404SJohn Birrell 	ushort_t retid;
825*1673e404SJohn Birrell 	GElf_Sym *sym;
826*1673e404SJohn Birrell 	int i;
827*1673e404SJohn Birrell 
828*1673e404SJohn Birrell 	symit_reset(si);
829*1673e404SJohn Birrell 	while (dptr < buf + bufsz) {
830*1673e404SJohn Birrell 		void *v = (void *) dptr;
831*1673e404SJohn Birrell 		info = *((ushort_t *)v);
832*1673e404SJohn Birrell 		dptr += 2;
833*1673e404SJohn Birrell 
834*1673e404SJohn Birrell 		if (!(sym = symit_next(si, STT_FUNC)) && info != 0)
835*1673e404SJohn Birrell 			parseterminate("Unexpected end of function symbols");
836*1673e404SJohn Birrell 
837*1673e404SJohn Birrell 		if (info == 0) {
838*1673e404SJohn Birrell 			debug(3, "Skipping null function (%s)\n",
839*1673e404SJohn Birrell 			    symit_name(si));
840*1673e404SJohn Birrell 			continue;
841*1673e404SJohn Birrell 		}
842*1673e404SJohn Birrell 
843*1673e404SJohn Birrell 		v = (void *) dptr;
844*1673e404SJohn Birrell 		retid = *((ushort_t *)v);
845*1673e404SJohn Birrell 		dptr += 2;
846*1673e404SJohn Birrell 
847*1673e404SJohn Birrell 		if (retid >= tdsize)
848*1673e404SJohn Birrell 			parseterminate("Reference to invalid type %d", retid);
849*1673e404SJohn Birrell 
850*1673e404SJohn Birrell 		ii = iidesc_new(symit_name(si));
851*1673e404SJohn Birrell 		ii->ii_dtype = tdarr[retid];
852*1673e404SJohn Birrell 		if (GELF_ST_BIND(sym->st_info) == STB_LOCAL) {
853*1673e404SJohn Birrell 			ii->ii_type = II_SFUN;
854*1673e404SJohn Birrell 			ii->ii_owner = xstrdup(symit_curfile(si));
855*1673e404SJohn Birrell 		} else
856*1673e404SJohn Birrell 			ii->ii_type = II_GFUN;
857*1673e404SJohn Birrell 		ii->ii_nargs = CTF_INFO_VLEN(info);
858*1673e404SJohn Birrell 		if (ii->ii_nargs)
859*1673e404SJohn Birrell 			ii->ii_args =
860*1673e404SJohn Birrell 			    xmalloc(sizeof (tdesc_t *) * ii->ii_nargs);
861*1673e404SJohn Birrell 
862*1673e404SJohn Birrell 		for (i = 0; i < ii->ii_nargs; i++, dptr += 2) {
863*1673e404SJohn Birrell 			v = (void *) dptr;
864*1673e404SJohn Birrell 			ushort_t id = *((ushort_t *)v);
865*1673e404SJohn Birrell 			if (id >= tdsize)
866*1673e404SJohn Birrell 				parseterminate("Reference to invalid type %d",
867*1673e404SJohn Birrell 				    id);
868*1673e404SJohn Birrell 			ii->ii_args[i] = tdarr[id];
869*1673e404SJohn Birrell 		}
870*1673e404SJohn Birrell 
871*1673e404SJohn Birrell 		if (ii->ii_nargs && ii->ii_args[ii->ii_nargs - 1] == NULL) {
872*1673e404SJohn Birrell 			ii->ii_nargs--;
873*1673e404SJohn Birrell 			ii->ii_vargs = 1;
874*1673e404SJohn Birrell 		}
875*1673e404SJohn Birrell 
876*1673e404SJohn Birrell 		hash_add(td->td_iihash, ii);
877*1673e404SJohn Birrell 
878*1673e404SJohn Birrell 		debug(3, "Resurrected %s function %s (%d, %d args)\n",
879*1673e404SJohn Birrell 		    (ii->ii_type == II_GFUN ? "global" : "static"),
880*1673e404SJohn Birrell 		    ii->ii_name, retid, ii->ii_nargs);
881*1673e404SJohn Birrell 	}
882*1673e404SJohn Birrell }
883*1673e404SJohn Birrell 
884*1673e404SJohn Birrell static void
885*1673e404SJohn Birrell resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
886*1673e404SJohn Birrell     caddr_t ctfdata, int maxid)
887*1673e404SJohn Birrell {
888*1673e404SJohn Birrell 	caddr_t buf = ctfdata + h->cth_typeoff;
889*1673e404SJohn Birrell 	size_t bufsz = h->cth_stroff - h->cth_typeoff;
890*1673e404SJohn Birrell 	caddr_t sbuf = ctfdata + h->cth_stroff;
891*1673e404SJohn Birrell 	caddr_t dptr = buf;
892*1673e404SJohn Birrell 	tdesc_t *tdp;
893*1673e404SJohn Birrell 	uint_t data;
894*1673e404SJohn Birrell 	uint_t encoding;
895*1673e404SJohn Birrell 	size_t size, increment;
896*1673e404SJohn Birrell 	int tcnt;
897*1673e404SJohn Birrell 	int iicnt = 0;
898*1673e404SJohn Birrell 	tid_t tid, argid;
899*1673e404SJohn Birrell 	int kind, vlen;
900*1673e404SJohn Birrell 	int i;
901*1673e404SJohn Birrell 
902*1673e404SJohn Birrell 	elist_t **epp;
903*1673e404SJohn Birrell 	mlist_t **mpp;
904*1673e404SJohn Birrell 	intr_t *ip;
905*1673e404SJohn Birrell 
906*1673e404SJohn Birrell 	ctf_type_t *ctt;
907*1673e404SJohn Birrell 	ctf_array_t *cta;
908*1673e404SJohn Birrell 	ctf_enum_t *cte;
909*1673e404SJohn Birrell 
910*1673e404SJohn Birrell 	/*
911*1673e404SJohn Birrell 	 * A maxid of zero indicates a request to resurrect all types, so reset
912*1673e404SJohn Birrell 	 * maxid to the maximum type id.
913*1673e404SJohn Birrell 	 */
914*1673e404SJohn Birrell 	if (maxid == 0)
915*1673e404SJohn Birrell 		maxid = CTF_MAX_TYPE;
916*1673e404SJohn Birrell 
917*1673e404SJohn Birrell 	for (dptr = buf, tcnt = 0, tid = 1; dptr < buf + bufsz; tcnt++, tid++) {
918*1673e404SJohn Birrell 		if (tid > maxid)
919*1673e404SJohn Birrell 			break;
920*1673e404SJohn Birrell 
921*1673e404SJohn Birrell 		if (tid >= tdsize)
922*1673e404SJohn Birrell 			parseterminate("Reference to invalid type %d", tid);
923*1673e404SJohn Birrell 
924*1673e404SJohn Birrell 		void *v = (void *) dptr;
925*1673e404SJohn Birrell 		ctt = v;
926*1673e404SJohn Birrell 
927*1673e404SJohn Birrell 		get_ctt_size(ctt, &size, &increment);
928*1673e404SJohn Birrell 		dptr += increment;
929*1673e404SJohn Birrell 
930*1673e404SJohn Birrell 		tdp = tdarr[tid];
931*1673e404SJohn Birrell 
932*1673e404SJohn Birrell 		if (CTF_NAME_STID(ctt->ctt_name) != CTF_STRTAB_0)
933*1673e404SJohn Birrell 			parseterminate(
934*1673e404SJohn Birrell 				"Unable to cope with non-zero strtab id");
935*1673e404SJohn Birrell 		if (CTF_NAME_OFFSET(ctt->ctt_name) != 0) {
936*1673e404SJohn Birrell 			tdp->t_name =
937*1673e404SJohn Birrell 			    xstrdup(sbuf + CTF_NAME_OFFSET(ctt->ctt_name));
938*1673e404SJohn Birrell 		} else
939*1673e404SJohn Birrell 			tdp->t_name = NULL;
940*1673e404SJohn Birrell 
941*1673e404SJohn Birrell 		kind = CTF_INFO_KIND(ctt->ctt_info);
942*1673e404SJohn Birrell 		vlen = CTF_INFO_VLEN(ctt->ctt_info);
943*1673e404SJohn Birrell 
944*1673e404SJohn Birrell 		switch (kind) {
945*1673e404SJohn Birrell 		case CTF_K_INTEGER:
946*1673e404SJohn Birrell 			tdp->t_type = INTRINSIC;
947*1673e404SJohn Birrell 			tdp->t_size = size;
948*1673e404SJohn Birrell 
949*1673e404SJohn Birrell 			v = (void *) dptr;
950*1673e404SJohn Birrell 			data = *((uint_t *)v);
951*1673e404SJohn Birrell 			dptr += sizeof (uint_t);
952*1673e404SJohn Birrell 			encoding = CTF_INT_ENCODING(data);
953*1673e404SJohn Birrell 
954*1673e404SJohn Birrell 			ip = xmalloc(sizeof (intr_t));
955*1673e404SJohn Birrell 			ip->intr_type = INTR_INT;
956*1673e404SJohn Birrell 			ip->intr_signed = (encoding & CTF_INT_SIGNED) ? 1 : 0;
957*1673e404SJohn Birrell 
958*1673e404SJohn Birrell 			if (encoding & CTF_INT_CHAR)
959*1673e404SJohn Birrell 				ip->intr_iformat = 'c';
960*1673e404SJohn Birrell 			else if (encoding & CTF_INT_BOOL)
961*1673e404SJohn Birrell 				ip->intr_iformat = 'b';
962*1673e404SJohn Birrell 			else if (encoding & CTF_INT_VARARGS)
963*1673e404SJohn Birrell 				ip->intr_iformat = 'v';
964*1673e404SJohn Birrell 			else
965*1673e404SJohn Birrell 				ip->intr_iformat = '\0';
966*1673e404SJohn Birrell 
967*1673e404SJohn Birrell 			ip->intr_offset = CTF_INT_OFFSET(data);
968*1673e404SJohn Birrell 			ip->intr_nbits = CTF_INT_BITS(data);
969*1673e404SJohn Birrell 			tdp->t_intr = ip;
970*1673e404SJohn Birrell 			break;
971*1673e404SJohn Birrell 
972*1673e404SJohn Birrell 		case CTF_K_FLOAT:
973*1673e404SJohn Birrell 			tdp->t_type = INTRINSIC;
974*1673e404SJohn Birrell 			tdp->t_size = size;
975*1673e404SJohn Birrell 
976*1673e404SJohn Birrell 			v = (void *) dptr;
977*1673e404SJohn Birrell 			data = *((uint_t *)v);
978*1673e404SJohn Birrell 			dptr += sizeof (uint_t);
979*1673e404SJohn Birrell 
980*1673e404SJohn Birrell 			ip = xcalloc(sizeof (intr_t));
981*1673e404SJohn Birrell 			ip->intr_type = INTR_REAL;
982*1673e404SJohn Birrell 			ip->intr_fformat = CTF_FP_ENCODING(data);
983*1673e404SJohn Birrell 			ip->intr_offset = CTF_FP_OFFSET(data);
984*1673e404SJohn Birrell 			ip->intr_nbits = CTF_FP_BITS(data);
985*1673e404SJohn Birrell 			tdp->t_intr = ip;
986*1673e404SJohn Birrell 			break;
987*1673e404SJohn Birrell 
988*1673e404SJohn Birrell 		case CTF_K_POINTER:
989*1673e404SJohn Birrell 			tdp->t_type = POINTER;
990*1673e404SJohn Birrell 			tdp->t_tdesc = tdarr[ctt->ctt_type];
991*1673e404SJohn Birrell 			break;
992*1673e404SJohn Birrell 
993*1673e404SJohn Birrell 		case CTF_K_ARRAY:
994*1673e404SJohn Birrell 			tdp->t_type = ARRAY;
995*1673e404SJohn Birrell 			tdp->t_size = size;
996*1673e404SJohn Birrell 
997*1673e404SJohn Birrell 			v = (void *) dptr;
998*1673e404SJohn Birrell 			cta = v;
999*1673e404SJohn Birrell 			dptr += sizeof (ctf_array_t);
1000*1673e404SJohn Birrell 
1001*1673e404SJohn Birrell 			tdp->t_ardef = xmalloc(sizeof (ardef_t));
1002*1673e404SJohn Birrell 			tdp->t_ardef->ad_contents = tdarr[cta->cta_contents];
1003*1673e404SJohn Birrell 			tdp->t_ardef->ad_idxtype = tdarr[cta->cta_index];
1004*1673e404SJohn Birrell 			tdp->t_ardef->ad_nelems = cta->cta_nelems;
1005*1673e404SJohn Birrell 			break;
1006*1673e404SJohn Birrell 
1007*1673e404SJohn Birrell 		case CTF_K_STRUCT:
1008*1673e404SJohn Birrell 		case CTF_K_UNION:
1009*1673e404SJohn Birrell 			tdp->t_type = (kind == CTF_K_STRUCT ? STRUCT : UNION);
1010*1673e404SJohn Birrell 			tdp->t_size = size;
1011*1673e404SJohn Birrell 
1012*1673e404SJohn Birrell 			if (size < CTF_LSTRUCT_THRESH) {
1013*1673e404SJohn Birrell 				for (i = 0, mpp = &tdp->t_members; i < vlen;
1014*1673e404SJohn Birrell 				    i++, mpp = &((*mpp)->ml_next)) {
1015*1673e404SJohn Birrell 					v = (void *) dptr;
1016*1673e404SJohn Birrell 					ctf_member_t *ctm = v;
1017*1673e404SJohn Birrell 					dptr += sizeof (ctf_member_t);
1018*1673e404SJohn Birrell 
1019*1673e404SJohn Birrell 					*mpp = xmalloc(sizeof (mlist_t));
1020*1673e404SJohn Birrell 					(*mpp)->ml_name = xstrdup(sbuf +
1021*1673e404SJohn Birrell 					    ctm->ctm_name);
1022*1673e404SJohn Birrell 					(*mpp)->ml_type = tdarr[ctm->ctm_type];
1023*1673e404SJohn Birrell 					(*mpp)->ml_offset = ctm->ctm_offset;
1024*1673e404SJohn Birrell 					(*mpp)->ml_size = 0;
1025*1673e404SJohn Birrell 				}
1026*1673e404SJohn Birrell 			} else {
1027*1673e404SJohn Birrell 				for (i = 0, mpp = &tdp->t_members; i < vlen;
1028*1673e404SJohn Birrell 				    i++, mpp = &((*mpp)->ml_next)) {
1029*1673e404SJohn Birrell 					v = (void *) dptr;
1030*1673e404SJohn Birrell 					ctf_lmember_t *ctlm = v;
1031*1673e404SJohn Birrell 					dptr += sizeof (ctf_lmember_t);
1032*1673e404SJohn Birrell 
1033*1673e404SJohn Birrell 					*mpp = xmalloc(sizeof (mlist_t));
1034*1673e404SJohn Birrell 					(*mpp)->ml_name = xstrdup(sbuf +
1035*1673e404SJohn Birrell 					    ctlm->ctlm_name);
1036*1673e404SJohn Birrell 					(*mpp)->ml_type =
1037*1673e404SJohn Birrell 					    tdarr[ctlm->ctlm_type];
1038*1673e404SJohn Birrell 					(*mpp)->ml_offset =
1039*1673e404SJohn Birrell 					    (int)CTF_LMEM_OFFSET(ctlm);
1040*1673e404SJohn Birrell 					(*mpp)->ml_size = 0;
1041*1673e404SJohn Birrell 				}
1042*1673e404SJohn Birrell 			}
1043*1673e404SJohn Birrell 
1044*1673e404SJohn Birrell 			*mpp = NULL;
1045*1673e404SJohn Birrell 			break;
1046*1673e404SJohn Birrell 
1047*1673e404SJohn Birrell 		case CTF_K_ENUM:
1048*1673e404SJohn Birrell 			tdp->t_type = ENUM;
1049*1673e404SJohn Birrell 			tdp->t_size = size;
1050*1673e404SJohn Birrell 
1051*1673e404SJohn Birrell 			for (i = 0, epp = &tdp->t_emem; i < vlen;
1052*1673e404SJohn Birrell 			    i++, epp = &((*epp)->el_next)) {
1053*1673e404SJohn Birrell 				v = (void *) dptr;
1054*1673e404SJohn Birrell 				cte = v;
1055*1673e404SJohn Birrell 				dptr += sizeof (ctf_enum_t);
1056*1673e404SJohn Birrell 
1057*1673e404SJohn Birrell 				*epp = xmalloc(sizeof (elist_t));
1058*1673e404SJohn Birrell 				(*epp)->el_name = xstrdup(sbuf + cte->cte_name);
1059*1673e404SJohn Birrell 				(*epp)->el_number = cte->cte_value;
1060*1673e404SJohn Birrell 			}
1061*1673e404SJohn Birrell 			*epp = NULL;
1062*1673e404SJohn Birrell 			break;
1063*1673e404SJohn Birrell 
1064*1673e404SJohn Birrell 		case CTF_K_FORWARD:
1065*1673e404SJohn Birrell 			tdp->t_type = FORWARD;
1066*1673e404SJohn Birrell 			list_add(&td->td_fwdlist, tdp);
1067*1673e404SJohn Birrell 			break;
1068*1673e404SJohn Birrell 
1069*1673e404SJohn Birrell 		case CTF_K_TYPEDEF:
1070*1673e404SJohn Birrell 			tdp->t_type = TYPEDEF;
1071*1673e404SJohn Birrell 			tdp->t_tdesc = tdarr[ctt->ctt_type];
1072*1673e404SJohn Birrell 			break;
1073*1673e404SJohn Birrell 
1074*1673e404SJohn Birrell 		case CTF_K_VOLATILE:
1075*1673e404SJohn Birrell 			tdp->t_type = VOLATILE;
1076*1673e404SJohn Birrell 			tdp->t_tdesc = tdarr[ctt->ctt_type];
1077*1673e404SJohn Birrell 			break;
1078*1673e404SJohn Birrell 
1079*1673e404SJohn Birrell 		case CTF_K_CONST:
1080*1673e404SJohn Birrell 			tdp->t_type = CONST;
1081*1673e404SJohn Birrell 			tdp->t_tdesc = tdarr[ctt->ctt_type];
1082*1673e404SJohn Birrell 			break;
1083*1673e404SJohn Birrell 
1084*1673e404SJohn Birrell 		case CTF_K_FUNCTION:
1085*1673e404SJohn Birrell 			tdp->t_type = FUNCTION;
1086*1673e404SJohn Birrell 			tdp->t_fndef = xcalloc(sizeof (fndef_t));
1087*1673e404SJohn Birrell 			tdp->t_fndef->fn_ret = tdarr[ctt->ctt_type];
1088*1673e404SJohn Birrell 
1089*1673e404SJohn Birrell 			v = (void *) (dptr + (sizeof (ushort_t) * (vlen - 1)));
1090*1673e404SJohn Birrell 			if (vlen > 0 && *(ushort_t *)v == 0)
1091*1673e404SJohn Birrell 				tdp->t_fndef->fn_vargs = 1;
1092*1673e404SJohn Birrell 
1093*1673e404SJohn Birrell 			tdp->t_fndef->fn_nargs = vlen - tdp->t_fndef->fn_vargs;
1094*1673e404SJohn Birrell 			tdp->t_fndef->fn_args = xcalloc(sizeof (tdesc_t) *
1095*1673e404SJohn Birrell 			    vlen - tdp->t_fndef->fn_vargs);
1096*1673e404SJohn Birrell 
1097*1673e404SJohn Birrell 			for (i = 0; i < vlen; i++) {
1098*1673e404SJohn Birrell 				v = (void *) dptr;
1099*1673e404SJohn Birrell 				argid = *(ushort_t *)v;
1100*1673e404SJohn Birrell 				dptr += sizeof (ushort_t);
1101*1673e404SJohn Birrell 
1102*1673e404SJohn Birrell 				if (argid != 0)
1103*1673e404SJohn Birrell 					tdp->t_fndef->fn_args[i] = tdarr[argid];
1104*1673e404SJohn Birrell 			}
1105*1673e404SJohn Birrell 
1106*1673e404SJohn Birrell 			if (vlen & 1)
1107*1673e404SJohn Birrell 				dptr += sizeof (ushort_t);
1108*1673e404SJohn Birrell 			break;
1109*1673e404SJohn Birrell 
1110*1673e404SJohn Birrell 		case CTF_K_RESTRICT:
1111*1673e404SJohn Birrell 			tdp->t_type = RESTRICT;
1112*1673e404SJohn Birrell 			tdp->t_tdesc = tdarr[ctt->ctt_type];
1113*1673e404SJohn Birrell 			break;
1114*1673e404SJohn Birrell 
1115*1673e404SJohn Birrell 		case CTF_K_UNKNOWN:
1116*1673e404SJohn Birrell 			break;
1117*1673e404SJohn Birrell 
1118*1673e404SJohn Birrell 		default:
1119*1673e404SJohn Birrell 			warning("Can't parse unknown CTF type %d\n", kind);
1120*1673e404SJohn Birrell 		}
1121*1673e404SJohn Birrell 
1122*1673e404SJohn Birrell 		if (CTF_INFO_ISROOT(ctt->ctt_info)) {
1123*1673e404SJohn Birrell 			iidesc_t *ii = iidesc_new(tdp->t_name);
1124*1673e404SJohn Birrell 			if (tdp->t_type == STRUCT || tdp->t_type == UNION ||
1125*1673e404SJohn Birrell 			    tdp->t_type == ENUM)
1126*1673e404SJohn Birrell 				ii->ii_type = II_SOU;
1127*1673e404SJohn Birrell 			else
1128*1673e404SJohn Birrell 				ii->ii_type = II_TYPE;
1129*1673e404SJohn Birrell 			ii->ii_dtype = tdp;
1130*1673e404SJohn Birrell 			hash_add(td->td_iihash, ii);
1131*1673e404SJohn Birrell 
1132*1673e404SJohn Birrell 			iicnt++;
1133*1673e404SJohn Birrell 		}
1134*1673e404SJohn Birrell 
1135*1673e404SJohn Birrell 		debug(3, "Resurrected %d %stype %s (%d)\n", tdp->t_type,
1136*1673e404SJohn Birrell 		    (CTF_INFO_ISROOT(ctt->ctt_info) ? "root " : ""),
1137*1673e404SJohn Birrell 		    tdesc_name(tdp), tdp->t_id);
1138*1673e404SJohn Birrell 	}
1139*1673e404SJohn Birrell 
1140*1673e404SJohn Birrell 	debug(3, "Resurrected %d types (%d were roots)\n", tcnt, iicnt);
1141*1673e404SJohn Birrell }
1142*1673e404SJohn Birrell 
1143*1673e404SJohn Birrell /*
1144*1673e404SJohn Birrell  * For lack of other inspiration, we're going to take the boring route.  We
1145*1673e404SJohn Birrell  * count the number of types.  This lets us malloc that many tdesc structs
1146*1673e404SJohn Birrell  * before we start filling them in.  This has the advantage of allowing us to
1147*1673e404SJohn Birrell  * avoid a merge-esque remap step.
1148*1673e404SJohn Birrell  */
1149*1673e404SJohn Birrell static tdata_t *
1150*1673e404SJohn Birrell ctf_parse(ctf_header_t *h, caddr_t buf, symit_data_t *si, char *label)
1151*1673e404SJohn Birrell {
1152*1673e404SJohn Birrell 	tdata_t *td = tdata_new();
1153*1673e404SJohn Birrell 	tdesc_t **tdarr;
1154*1673e404SJohn Birrell 	int ntypes = count_types(h, buf);
1155*1673e404SJohn Birrell 	int idx, i;
1156*1673e404SJohn Birrell 
1157*1673e404SJohn Birrell 	/* shudder */
1158*1673e404SJohn Birrell 	tdarr = xcalloc(sizeof (tdesc_t *) * (ntypes + 1));
1159*1673e404SJohn Birrell 	tdarr[0] = NULL;
1160*1673e404SJohn Birrell 	for (i = 1; i <= ntypes; i++) {
1161*1673e404SJohn Birrell 		tdarr[i] = xcalloc(sizeof (tdesc_t));
1162*1673e404SJohn Birrell 		tdarr[i]->t_id = i;
1163*1673e404SJohn Birrell 	}
1164*1673e404SJohn Birrell 
1165*1673e404SJohn Birrell 	td->td_parlabel = xstrdup(buf + h->cth_stroff + h->cth_parlabel);
1166*1673e404SJohn Birrell 
1167*1673e404SJohn Birrell 	/* we have the technology - we can rebuild them */
1168*1673e404SJohn Birrell 	idx = resurrect_labels(h, td, buf, label);
1169*1673e404SJohn Birrell 
1170*1673e404SJohn Birrell 	resurrect_objects(h, td, tdarr, ntypes + 1, buf, si);
1171*1673e404SJohn Birrell 	resurrect_functions(h, td, tdarr, ntypes + 1, buf, si);
1172*1673e404SJohn Birrell 	resurrect_types(h, td, tdarr, ntypes + 1, buf, idx);
1173*1673e404SJohn Birrell 
1174*1673e404SJohn Birrell 	free(tdarr);
1175*1673e404SJohn Birrell 
1176*1673e404SJohn Birrell 	td->td_nextid = ntypes + 1;
1177*1673e404SJohn Birrell 
1178*1673e404SJohn Birrell 	return (td);
1179*1673e404SJohn Birrell }
1180*1673e404SJohn Birrell 
1181*1673e404SJohn Birrell static size_t
1182*1673e404SJohn Birrell decompress_ctf(caddr_t cbuf, size_t cbufsz, caddr_t dbuf, size_t dbufsz)
1183*1673e404SJohn Birrell {
1184*1673e404SJohn Birrell 	z_stream zstr;
1185*1673e404SJohn Birrell 	int rc;
1186*1673e404SJohn Birrell 
1187*1673e404SJohn Birrell 	zstr.zalloc = (alloc_func)0;
1188*1673e404SJohn Birrell 	zstr.zfree = (free_func)0;
1189*1673e404SJohn Birrell 	zstr.opaque = (voidpf)0;
1190*1673e404SJohn Birrell 
1191*1673e404SJohn Birrell 	zstr.next_in = (Bytef *)cbuf;
1192*1673e404SJohn Birrell 	zstr.avail_in = cbufsz;
1193*1673e404SJohn Birrell 	zstr.next_out = (Bytef *)dbuf;
1194*1673e404SJohn Birrell 	zstr.avail_out = dbufsz;
1195*1673e404SJohn Birrell 
1196*1673e404SJohn Birrell 	if ((rc = inflateInit(&zstr)) != Z_OK ||
1197*1673e404SJohn Birrell 	    (rc = inflate(&zstr, Z_NO_FLUSH)) != Z_STREAM_END ||
1198*1673e404SJohn Birrell 	    (rc = inflateEnd(&zstr)) != Z_OK) {
1199*1673e404SJohn Birrell 		warning("CTF decompress zlib error %s\n", zError(rc));
1200*1673e404SJohn Birrell 		return (0);
1201*1673e404SJohn Birrell 	}
1202*1673e404SJohn Birrell 
1203*1673e404SJohn Birrell 	debug(3, "reflated %lu bytes to %lu, pointer at %d\n",
1204*1673e404SJohn Birrell 	    zstr.total_in, zstr.total_out, (caddr_t)zstr.next_in - cbuf);
1205*1673e404SJohn Birrell 
1206*1673e404SJohn Birrell 	return (zstr.total_out);
1207*1673e404SJohn Birrell }
1208*1673e404SJohn Birrell 
1209*1673e404SJohn Birrell /*
1210*1673e404SJohn Birrell  * Reconstruct the type tree from a given buffer of CTF data.  Only the types
1211*1673e404SJohn Birrell  * up to the type associated with the provided label, inclusive, will be
1212*1673e404SJohn Birrell  * reconstructed.  If a NULL label is provided, all types will be reconstructed.
1213*1673e404SJohn Birrell  *
1214*1673e404SJohn Birrell  * This function won't work on files that have been uniquified.
1215*1673e404SJohn Birrell  */
1216*1673e404SJohn Birrell tdata_t *
1217*1673e404SJohn Birrell ctf_load(char *file, caddr_t buf, size_t bufsz, symit_data_t *si, char *label)
1218*1673e404SJohn Birrell {
1219*1673e404SJohn Birrell 	ctf_header_t *h;
1220*1673e404SJohn Birrell 	caddr_t ctfdata;
1221*1673e404SJohn Birrell 	size_t ctfdatasz;
1222*1673e404SJohn Birrell 	tdata_t *td;
1223*1673e404SJohn Birrell 
1224*1673e404SJohn Birrell 	curfile = file;
1225*1673e404SJohn Birrell 
1226*1673e404SJohn Birrell 	if (bufsz < sizeof (ctf_header_t))
1227*1673e404SJohn Birrell 		parseterminate("Corrupt CTF - short header");
1228*1673e404SJohn Birrell 
1229*1673e404SJohn Birrell 	void *v = (void *) buf;
1230*1673e404SJohn Birrell 	h = v;
1231*1673e404SJohn Birrell 	buf += sizeof (ctf_header_t);
1232*1673e404SJohn Birrell 	bufsz -= sizeof (ctf_header_t);
1233*1673e404SJohn Birrell 
1234*1673e404SJohn Birrell 	if (h->cth_magic != CTF_MAGIC)
1235*1673e404SJohn Birrell 		parseterminate("Corrupt CTF - bad magic 0x%x", h->cth_magic);
1236*1673e404SJohn Birrell 
1237*1673e404SJohn Birrell 	if (h->cth_version != CTF_VERSION)
1238*1673e404SJohn Birrell 		parseterminate("Unknown CTF version %d", h->cth_version);
1239*1673e404SJohn Birrell 
1240*1673e404SJohn Birrell 	ctfdatasz = h->cth_stroff + h->cth_strlen;
1241*1673e404SJohn Birrell 	if (h->cth_flags & CTF_F_COMPRESS) {
1242*1673e404SJohn Birrell 		size_t actual;
1243*1673e404SJohn Birrell 
1244*1673e404SJohn Birrell 		ctfdata = xmalloc(ctfdatasz);
1245*1673e404SJohn Birrell 		if ((actual = decompress_ctf(buf, bufsz, ctfdata, ctfdatasz)) !=
1246*1673e404SJohn Birrell 		    ctfdatasz) {
1247*1673e404SJohn Birrell 			parseterminate("Corrupt CTF - short decompression "
1248*1673e404SJohn Birrell 			    "(was %d, expecting %d)", actual, ctfdatasz);
1249*1673e404SJohn Birrell 		}
1250*1673e404SJohn Birrell 	} else {
1251*1673e404SJohn Birrell 		ctfdata = buf;
1252*1673e404SJohn Birrell 		ctfdatasz = bufsz;
1253*1673e404SJohn Birrell 	}
1254*1673e404SJohn Birrell 
1255*1673e404SJohn Birrell 	td = ctf_parse(h, ctfdata, si, label);
1256*1673e404SJohn Birrell 
1257*1673e404SJohn Birrell 	if (h->cth_flags & CTF_F_COMPRESS)
1258*1673e404SJohn Birrell 		free(ctfdata);
1259*1673e404SJohn Birrell 
1260*1673e404SJohn Birrell 	curfile = NULL;
1261*1673e404SJohn Birrell 
1262*1673e404SJohn Birrell 	return (td);
1263*1673e404SJohn Birrell }
1264