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