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