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