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