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