11673e404SJohn Birrell /* 21673e404SJohn Birrell * CDDL HEADER START 31673e404SJohn Birrell * 41673e404SJohn Birrell * The contents of this file are subject to the terms of the 51673e404SJohn Birrell * Common Development and Distribution License (the "License"). 61673e404SJohn Birrell * You may not use this file except in compliance with the License. 71673e404SJohn Birrell * 81673e404SJohn Birrell * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91673e404SJohn Birrell * or http://www.opensolaris.org/os/licensing. 101673e404SJohn Birrell * See the License for the specific language governing permissions 111673e404SJohn Birrell * and limitations under the License. 121673e404SJohn Birrell * 131673e404SJohn Birrell * When distributing Covered Code, include this CDDL HEADER in each 141673e404SJohn Birrell * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151673e404SJohn Birrell * If applicable, add the following below this CDDL HEADER, with the 161673e404SJohn Birrell * fields enclosed by brackets "[]" replaced with your own identifying 171673e404SJohn Birrell * information: Portions Copyright [yyyy] [name of copyright owner] 181673e404SJohn Birrell * 191673e404SJohn Birrell * CDDL HEADER END 201673e404SJohn Birrell */ 211673e404SJohn Birrell /* 221673e404SJohn Birrell * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 231673e404SJohn Birrell * Use is subject to license terms. 241673e404SJohn Birrell */ 251673e404SJohn Birrell 261673e404SJohn Birrell #pragma ident "%Z%%M% %I% %E% SMI" 271673e404SJohn Birrell 281673e404SJohn Birrell /* 291673e404SJohn Birrell * Create and parse buffers containing CTF data. 301673e404SJohn Birrell */ 311673e404SJohn Birrell 321673e404SJohn Birrell #include <sys/types.h> 331673e404SJohn Birrell #include <stdio.h> 341673e404SJohn Birrell #include <stdlib.h> 351673e404SJohn Birrell #include <strings.h> 361673e404SJohn Birrell #include <ctype.h> 371673e404SJohn Birrell #include <zlib.h> 381673e404SJohn Birrell #include <elf.h> 391673e404SJohn Birrell 401673e404SJohn Birrell #include "ctf_headers.h" 411673e404SJohn Birrell #include "ctftools.h" 421673e404SJohn Birrell #include "strtab.h" 431673e404SJohn Birrell #include "memory.h" 441673e404SJohn Birrell 451673e404SJohn Birrell /* 461673e404SJohn Birrell * Name of the file currently being read, used to print error messages. We 471673e404SJohn Birrell * assume that only one file will be read at a time, and thus make no attempt 481673e404SJohn Birrell * to allow curfile to be used simultaneously by multiple threads. 491673e404SJohn Birrell * 501673e404SJohn Birrell * The value is only valid during a call to ctf_load. 511673e404SJohn Birrell */ 521673e404SJohn Birrell char *curfile; 531673e404SJohn Birrell 541673e404SJohn Birrell #define CTF_BUF_CHUNK_SIZE (64 * 1024) 551673e404SJohn Birrell #define RES_BUF_CHUNK_SIZE (64 * 1024) 561673e404SJohn Birrell 571673e404SJohn Birrell struct ctf_buf { 581673e404SJohn Birrell strtab_t ctb_strtab; /* string table */ 591673e404SJohn Birrell caddr_t ctb_base; /* pointer to base of buffer */ 601673e404SJohn Birrell caddr_t ctb_end; /* pointer to end of buffer */ 611673e404SJohn Birrell caddr_t ctb_ptr; /* pointer to empty buffer space */ 621673e404SJohn Birrell size_t ctb_size; /* size of buffer */ 631673e404SJohn Birrell int nptent; /* number of processed types */ 641673e404SJohn Birrell int ntholes; /* number of type holes */ 651673e404SJohn Birrell }; 661673e404SJohn Birrell 671673e404SJohn Birrell /*PRINTFLIKE1*/ 681673e404SJohn Birrell static void 694cc75139SJohn Birrell parseterminate(const char *fmt, ...) 701673e404SJohn Birrell { 711673e404SJohn Birrell static char msgbuf[1024]; /* sigh */ 721673e404SJohn Birrell va_list ap; 731673e404SJohn Birrell 741673e404SJohn Birrell va_start(ap, fmt); 751673e404SJohn Birrell vsnprintf(msgbuf, sizeof (msgbuf), fmt, ap); 761673e404SJohn Birrell va_end(ap); 771673e404SJohn Birrell 781673e404SJohn Birrell terminate("%s: %s\n", curfile, msgbuf); 791673e404SJohn Birrell } 801673e404SJohn Birrell 814cc75139SJohn Birrell static void 821673e404SJohn Birrell ctf_buf_grow(ctf_buf_t *b) 831673e404SJohn Birrell { 841673e404SJohn Birrell off_t ptroff = b->ctb_ptr - b->ctb_base; 851673e404SJohn Birrell 861673e404SJohn Birrell b->ctb_size += CTF_BUF_CHUNK_SIZE; 871673e404SJohn Birrell b->ctb_base = xrealloc(b->ctb_base, b->ctb_size); 881673e404SJohn Birrell b->ctb_end = b->ctb_base + b->ctb_size; 891673e404SJohn Birrell b->ctb_ptr = b->ctb_base + ptroff; 901673e404SJohn Birrell } 911673e404SJohn Birrell 924cc75139SJohn Birrell static ctf_buf_t * 931673e404SJohn Birrell ctf_buf_new(void) 941673e404SJohn Birrell { 951673e404SJohn Birrell ctf_buf_t *b = xcalloc(sizeof (ctf_buf_t)); 961673e404SJohn Birrell 971673e404SJohn Birrell strtab_create(&b->ctb_strtab); 981673e404SJohn Birrell ctf_buf_grow(b); 991673e404SJohn Birrell 1001673e404SJohn Birrell return (b); 1011673e404SJohn Birrell } 1021673e404SJohn Birrell 1034cc75139SJohn Birrell static void 1041673e404SJohn Birrell ctf_buf_free(ctf_buf_t *b) 1051673e404SJohn Birrell { 1061673e404SJohn Birrell strtab_destroy(&b->ctb_strtab); 1071673e404SJohn Birrell free(b->ctb_base); 1081673e404SJohn Birrell free(b); 1091673e404SJohn Birrell } 1101673e404SJohn Birrell 1114cc75139SJohn Birrell static uint_t 1121673e404SJohn Birrell ctf_buf_cur(ctf_buf_t *b) 1131673e404SJohn Birrell { 1141673e404SJohn Birrell return (b->ctb_ptr - b->ctb_base); 1151673e404SJohn Birrell } 1161673e404SJohn Birrell 1174cc75139SJohn Birrell static void 1184cc75139SJohn Birrell ctf_buf_write(ctf_buf_t *b, void const *p, size_t n) 1191673e404SJohn Birrell { 1201673e404SJohn Birrell size_t len; 1211673e404SJohn Birrell 1221673e404SJohn Birrell while (n != 0) { 1231673e404SJohn Birrell if (b->ctb_ptr == b->ctb_end) 1241673e404SJohn Birrell ctf_buf_grow(b); 1251673e404SJohn Birrell 1261673e404SJohn Birrell len = MIN((size_t)(b->ctb_end - b->ctb_ptr), n); 1271673e404SJohn Birrell bcopy(p, b->ctb_ptr, len); 1281673e404SJohn Birrell b->ctb_ptr += len; 1291673e404SJohn Birrell 1304cc75139SJohn Birrell p = (char const *)p + len; 1311673e404SJohn Birrell n -= len; 1321673e404SJohn Birrell } 1331673e404SJohn Birrell } 1341673e404SJohn Birrell 1351673e404SJohn Birrell static int 1364cc75139SJohn Birrell write_label(void *arg1, void *arg2) 1371673e404SJohn Birrell { 1384cc75139SJohn Birrell labelent_t *le = arg1; 1394cc75139SJohn Birrell ctf_buf_t *b = arg2; 1401673e404SJohn Birrell ctf_lblent_t ctl; 1411673e404SJohn Birrell 1421673e404SJohn Birrell ctl.ctl_label = strtab_insert(&b->ctb_strtab, le->le_name); 1431673e404SJohn Birrell ctl.ctl_typeidx = le->le_idx; 1441673e404SJohn Birrell 1451673e404SJohn Birrell ctf_buf_write(b, &ctl, sizeof (ctl)); 1461673e404SJohn Birrell 1471673e404SJohn Birrell return (1); 1481673e404SJohn Birrell } 1491673e404SJohn Birrell 1501673e404SJohn Birrell static void 1511673e404SJohn Birrell write_objects(iidesc_t *idp, ctf_buf_t *b) 1521673e404SJohn Birrell { 1531673e404SJohn Birrell ushort_t id = (idp ? idp->ii_dtype->t_id : 0); 1541673e404SJohn Birrell 1551673e404SJohn Birrell ctf_buf_write(b, &id, sizeof (id)); 1561673e404SJohn Birrell 1571673e404SJohn Birrell debug(3, "Wrote object %s (%d)\n", (idp ? idp->ii_name : "(null)"), id); 1581673e404SJohn Birrell } 1591673e404SJohn Birrell 1601673e404SJohn Birrell static void 1611673e404SJohn Birrell write_functions(iidesc_t *idp, ctf_buf_t *b) 1621673e404SJohn Birrell { 1631673e404SJohn Birrell ushort_t fdata[2]; 1641673e404SJohn Birrell ushort_t id; 1651673e404SJohn Birrell int nargs; 1661673e404SJohn Birrell int i; 1671673e404SJohn Birrell 1681673e404SJohn Birrell if (!idp) { 1691673e404SJohn Birrell fdata[0] = 0; 1701673e404SJohn Birrell ctf_buf_write(b, &fdata[0], sizeof (fdata[0])); 1711673e404SJohn Birrell 1721673e404SJohn Birrell debug(3, "Wrote function (null)\n"); 1731673e404SJohn Birrell return; 1741673e404SJohn Birrell } 1751673e404SJohn Birrell 1761673e404SJohn Birrell nargs = idp->ii_nargs + (idp->ii_vargs != 0); 1771673e404SJohn Birrell fdata[0] = CTF_TYPE_INFO(CTF_K_FUNCTION, 1, nargs); 1781673e404SJohn Birrell fdata[1] = idp->ii_dtype->t_id; 1791673e404SJohn Birrell ctf_buf_write(b, fdata, sizeof (fdata)); 1801673e404SJohn Birrell 1811673e404SJohn Birrell for (i = 0; i < idp->ii_nargs; i++) { 1821673e404SJohn Birrell id = idp->ii_args[i]->t_id; 1831673e404SJohn Birrell ctf_buf_write(b, &id, sizeof (id)); 1841673e404SJohn Birrell } 1851673e404SJohn Birrell 1861673e404SJohn Birrell if (idp->ii_vargs) { 1871673e404SJohn Birrell id = 0; 1881673e404SJohn Birrell ctf_buf_write(b, &id, sizeof (id)); 1891673e404SJohn Birrell } 1901673e404SJohn Birrell 1911673e404SJohn Birrell debug(3, "Wrote function %s (%d args)\n", idp->ii_name, nargs); 1921673e404SJohn Birrell } 1931673e404SJohn Birrell 1941673e404SJohn Birrell /* 1951673e404SJohn Birrell * Depending on the size of the type being described, either a ctf_stype_t (for 1961673e404SJohn Birrell * types with size < CTF_LSTRUCT_THRESH) or a ctf_type_t (all others) will be 1971673e404SJohn Birrell * written. We isolate the determination here so the rest of the writer code 1981673e404SJohn Birrell * doesn't need to care. 1991673e404SJohn Birrell */ 2001673e404SJohn Birrell static void 2011673e404SJohn Birrell write_sized_type_rec(ctf_buf_t *b, ctf_type_t *ctt, size_t size) 2021673e404SJohn Birrell { 2031673e404SJohn Birrell if (size > CTF_MAX_SIZE) { 2041673e404SJohn Birrell ctt->ctt_size = CTF_LSIZE_SENT; 2051673e404SJohn Birrell ctt->ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size); 2061673e404SJohn Birrell ctt->ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size); 2071673e404SJohn Birrell ctf_buf_write(b, ctt, sizeof (*ctt)); 2081673e404SJohn Birrell } else { 2091673e404SJohn Birrell ctf_stype_t *cts = (ctf_stype_t *)ctt; 2101673e404SJohn Birrell 2111673e404SJohn Birrell cts->ctt_size = (ushort_t)size; 2121673e404SJohn Birrell ctf_buf_write(b, cts, sizeof (*cts)); 2131673e404SJohn Birrell } 2141673e404SJohn Birrell } 2151673e404SJohn Birrell 2161673e404SJohn Birrell static void 2171673e404SJohn Birrell write_unsized_type_rec(ctf_buf_t *b, ctf_type_t *ctt) 2181673e404SJohn Birrell { 2191673e404SJohn Birrell ctf_stype_t *cts = (ctf_stype_t *)ctt; 2201673e404SJohn Birrell 2211673e404SJohn Birrell ctf_buf_write(b, cts, sizeof (*cts)); 2221673e404SJohn Birrell } 2231673e404SJohn Birrell 2241673e404SJohn Birrell static int 2254cc75139SJohn Birrell write_type(void *arg1, void *arg2) 2261673e404SJohn Birrell { 2274cc75139SJohn Birrell tdesc_t *tp = arg1; 2284cc75139SJohn Birrell ctf_buf_t *b = arg2; 2291673e404SJohn Birrell elist_t *ep; 2301673e404SJohn Birrell mlist_t *mp; 2311673e404SJohn Birrell intr_t *ip; 2321673e404SJohn Birrell 2331673e404SJohn Birrell size_t offset; 2341673e404SJohn Birrell uint_t encoding; 2351673e404SJohn Birrell uint_t data; 2361673e404SJohn Birrell int isroot = tp->t_flags & TDESC_F_ISROOT; 2371673e404SJohn Birrell int i; 2381673e404SJohn Birrell 2391673e404SJohn Birrell ctf_type_t ctt; 2401673e404SJohn Birrell ctf_array_t cta; 2411673e404SJohn Birrell ctf_member_t ctm; 2421673e404SJohn Birrell ctf_lmember_t ctlm; 2431673e404SJohn Birrell ctf_enum_t cte; 2441673e404SJohn Birrell ushort_t id; 2451673e404SJohn Birrell 2461673e404SJohn Birrell ctlm.ctlm_pad = 0; 2471673e404SJohn Birrell 2481673e404SJohn Birrell /* 2491673e404SJohn Birrell * There shouldn't be any holes in the type list (where a hole is 2501673e404SJohn Birrell * defined as two consecutive tdescs without consecutive ids), but 2511673e404SJohn Birrell * check for them just in case. If we do find holes, we need to make 2521673e404SJohn Birrell * fake entries to fill the holes, or we won't be able to reconstruct 2531673e404SJohn Birrell * the tree from the written data. 2541673e404SJohn Birrell */ 2551673e404SJohn Birrell if (++b->nptent < CTF_TYPE_TO_INDEX(tp->t_id)) { 2561673e404SJohn Birrell debug(2, "genctf: type hole from %d < x < %d\n", 2571673e404SJohn Birrell b->nptent - 1, CTF_TYPE_TO_INDEX(tp->t_id)); 2581673e404SJohn Birrell 2591673e404SJohn Birrell ctt.ctt_name = CTF_TYPE_NAME(CTF_STRTAB_0, 0); 2601673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(0, 0, 0); 2611673e404SJohn Birrell while (b->nptent < CTF_TYPE_TO_INDEX(tp->t_id)) { 2621673e404SJohn Birrell write_sized_type_rec(b, &ctt, 0); 2631673e404SJohn Birrell b->nptent++; 2641673e404SJohn Birrell } 2651673e404SJohn Birrell } 2661673e404SJohn Birrell 2671673e404SJohn Birrell offset = strtab_insert(&b->ctb_strtab, tp->t_name); 2681673e404SJohn Birrell ctt.ctt_name = CTF_TYPE_NAME(CTF_STRTAB_0, offset); 2691673e404SJohn Birrell 2701673e404SJohn Birrell switch (tp->t_type) { 2711673e404SJohn Birrell case INTRINSIC: 2721673e404SJohn Birrell ip = tp->t_intr; 2731673e404SJohn Birrell if (ip->intr_type == INTR_INT) 2741673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_INTEGER, 2751673e404SJohn Birrell isroot, 1); 2761673e404SJohn Birrell else 2771673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_FLOAT, isroot, 1); 2781673e404SJohn Birrell write_sized_type_rec(b, &ctt, tp->t_size); 2791673e404SJohn Birrell 2801673e404SJohn Birrell encoding = 0; 2811673e404SJohn Birrell 2821673e404SJohn Birrell if (ip->intr_type == INTR_INT) { 2831673e404SJohn Birrell if (ip->intr_signed) 2841673e404SJohn Birrell encoding |= CTF_INT_SIGNED; 2851673e404SJohn Birrell if (ip->intr_iformat == 'c') 2861673e404SJohn Birrell encoding |= CTF_INT_CHAR; 2871673e404SJohn Birrell else if (ip->intr_iformat == 'b') 2881673e404SJohn Birrell encoding |= CTF_INT_BOOL; 2891673e404SJohn Birrell else if (ip->intr_iformat == 'v') 2901673e404SJohn Birrell encoding |= CTF_INT_VARARGS; 2911673e404SJohn Birrell } else 2921673e404SJohn Birrell encoding = ip->intr_fformat; 2931673e404SJohn Birrell 2941673e404SJohn Birrell data = CTF_INT_DATA(encoding, ip->intr_offset, ip->intr_nbits); 2951673e404SJohn Birrell ctf_buf_write(b, &data, sizeof (data)); 2961673e404SJohn Birrell break; 2971673e404SJohn Birrell 2981673e404SJohn Birrell case POINTER: 2991673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_POINTER, isroot, 0); 3001673e404SJohn Birrell ctt.ctt_type = tp->t_tdesc->t_id; 3011673e404SJohn Birrell write_unsized_type_rec(b, &ctt); 3021673e404SJohn Birrell break; 3031673e404SJohn Birrell 3041673e404SJohn Birrell case ARRAY: 3051673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_ARRAY, isroot, 1); 3061673e404SJohn Birrell write_sized_type_rec(b, &ctt, tp->t_size); 3071673e404SJohn Birrell 3081673e404SJohn Birrell cta.cta_contents = tp->t_ardef->ad_contents->t_id; 3091673e404SJohn Birrell cta.cta_index = tp->t_ardef->ad_idxtype->t_id; 3101673e404SJohn Birrell cta.cta_nelems = tp->t_ardef->ad_nelems; 3111673e404SJohn Birrell ctf_buf_write(b, &cta, sizeof (cta)); 3121673e404SJohn Birrell break; 3131673e404SJohn Birrell 3141673e404SJohn Birrell case STRUCT: 3151673e404SJohn Birrell case UNION: 3161673e404SJohn Birrell for (i = 0, mp = tp->t_members; mp != NULL; mp = mp->ml_next) 3171673e404SJohn Birrell i++; /* count up struct or union members */ 3181673e404SJohn Birrell 3191673e404SJohn Birrell if (tp->t_type == STRUCT) 3201673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_STRUCT, isroot, i); 3211673e404SJohn Birrell else 3221673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_UNION, isroot, i); 3231673e404SJohn Birrell 3241673e404SJohn Birrell write_sized_type_rec(b, &ctt, tp->t_size); 3251673e404SJohn Birrell 3261673e404SJohn Birrell if (tp->t_size < CTF_LSTRUCT_THRESH) { 3271673e404SJohn Birrell for (mp = tp->t_members; mp != NULL; mp = mp->ml_next) { 3281673e404SJohn Birrell offset = strtab_insert(&b->ctb_strtab, 3291673e404SJohn Birrell mp->ml_name); 3301673e404SJohn Birrell 3311673e404SJohn Birrell ctm.ctm_name = CTF_TYPE_NAME(CTF_STRTAB_0, 3321673e404SJohn Birrell offset); 3331673e404SJohn Birrell ctm.ctm_type = mp->ml_type->t_id; 3341673e404SJohn Birrell ctm.ctm_offset = mp->ml_offset; 3351673e404SJohn Birrell ctf_buf_write(b, &ctm, sizeof (ctm)); 3361673e404SJohn Birrell } 3371673e404SJohn Birrell } else { 3381673e404SJohn Birrell for (mp = tp->t_members; mp != NULL; mp = mp->ml_next) { 3391673e404SJohn Birrell offset = strtab_insert(&b->ctb_strtab, 3401673e404SJohn Birrell mp->ml_name); 3411673e404SJohn Birrell 3421673e404SJohn Birrell ctlm.ctlm_name = CTF_TYPE_NAME(CTF_STRTAB_0, 3431673e404SJohn Birrell offset); 3441673e404SJohn Birrell ctlm.ctlm_type = mp->ml_type->t_id; 3451673e404SJohn Birrell ctlm.ctlm_offsethi = 3461673e404SJohn Birrell CTF_OFFSET_TO_LMEMHI(mp->ml_offset); 3471673e404SJohn Birrell ctlm.ctlm_offsetlo = 3481673e404SJohn Birrell CTF_OFFSET_TO_LMEMLO(mp->ml_offset); 3491673e404SJohn Birrell ctf_buf_write(b, &ctlm, sizeof (ctlm)); 3501673e404SJohn Birrell } 3511673e404SJohn Birrell } 3521673e404SJohn Birrell break; 3531673e404SJohn Birrell 3541673e404SJohn Birrell case ENUM: 3551673e404SJohn Birrell for (i = 0, ep = tp->t_emem; ep != NULL; ep = ep->el_next) 3561673e404SJohn Birrell i++; /* count up enum members */ 3571673e404SJohn Birrell 3581673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_ENUM, isroot, i); 3591673e404SJohn Birrell write_sized_type_rec(b, &ctt, tp->t_size); 3601673e404SJohn Birrell 3611673e404SJohn Birrell for (ep = tp->t_emem; ep != NULL; ep = ep->el_next) { 3621673e404SJohn Birrell offset = strtab_insert(&b->ctb_strtab, ep->el_name); 3631673e404SJohn Birrell cte.cte_name = CTF_TYPE_NAME(CTF_STRTAB_0, offset); 3641673e404SJohn Birrell cte.cte_value = ep->el_number; 3651673e404SJohn Birrell ctf_buf_write(b, &cte, sizeof (cte)); 3661673e404SJohn Birrell } 3671673e404SJohn Birrell break; 3681673e404SJohn Birrell 3691673e404SJohn Birrell case FORWARD: 3701673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_FORWARD, isroot, 0); 3711673e404SJohn Birrell ctt.ctt_type = 0; 3721673e404SJohn Birrell write_unsized_type_rec(b, &ctt); 3731673e404SJohn Birrell break; 3741673e404SJohn Birrell 3751673e404SJohn Birrell case TYPEDEF: 3761673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_TYPEDEF, isroot, 0); 3771673e404SJohn Birrell ctt.ctt_type = tp->t_tdesc->t_id; 3781673e404SJohn Birrell write_unsized_type_rec(b, &ctt); 3791673e404SJohn Birrell break; 3801673e404SJohn Birrell 3811673e404SJohn Birrell case VOLATILE: 3821673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_VOLATILE, isroot, 0); 3831673e404SJohn Birrell ctt.ctt_type = tp->t_tdesc->t_id; 3841673e404SJohn Birrell write_unsized_type_rec(b, &ctt); 3851673e404SJohn Birrell break; 3861673e404SJohn Birrell 3871673e404SJohn Birrell case CONST: 3881673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_CONST, isroot, 0); 3891673e404SJohn Birrell ctt.ctt_type = tp->t_tdesc->t_id; 3901673e404SJohn Birrell write_unsized_type_rec(b, &ctt); 3911673e404SJohn Birrell break; 3921673e404SJohn Birrell 3931673e404SJohn Birrell case FUNCTION: 3941673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_FUNCTION, isroot, 3951673e404SJohn Birrell tp->t_fndef->fn_nargs + tp->t_fndef->fn_vargs); 3961673e404SJohn Birrell ctt.ctt_type = tp->t_fndef->fn_ret->t_id; 3971673e404SJohn Birrell write_unsized_type_rec(b, &ctt); 3981673e404SJohn Birrell 3994cc75139SJohn Birrell for (i = 0; i < (int) tp->t_fndef->fn_nargs; i++) { 4001673e404SJohn Birrell id = tp->t_fndef->fn_args[i]->t_id; 4011673e404SJohn Birrell ctf_buf_write(b, &id, sizeof (id)); 4021673e404SJohn Birrell } 4031673e404SJohn Birrell 4041673e404SJohn Birrell if (tp->t_fndef->fn_vargs) { 4051673e404SJohn Birrell id = 0; 4061673e404SJohn Birrell ctf_buf_write(b, &id, sizeof (id)); 4071673e404SJohn Birrell i++; 4081673e404SJohn Birrell } 4091673e404SJohn Birrell 4101673e404SJohn Birrell if (i & 1) { 4111673e404SJohn Birrell id = 0; 4121673e404SJohn Birrell ctf_buf_write(b, &id, sizeof (id)); 4131673e404SJohn Birrell } 4141673e404SJohn Birrell break; 4151673e404SJohn Birrell 4161673e404SJohn Birrell case RESTRICT: 4171673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_RESTRICT, isroot, 0); 4181673e404SJohn Birrell ctt.ctt_type = tp->t_tdesc->t_id; 4191673e404SJohn Birrell write_unsized_type_rec(b, &ctt); 4201673e404SJohn Birrell break; 4211673e404SJohn Birrell 4221673e404SJohn Birrell default: 4231673e404SJohn Birrell warning("Can't write unknown type %d\n", tp->t_type); 4241673e404SJohn Birrell } 4251673e404SJohn Birrell 4261673e404SJohn Birrell debug(3, "Wrote type %d %s\n", tp->t_id, tdesc_name(tp)); 4271673e404SJohn Birrell 4281673e404SJohn Birrell return (1); 4291673e404SJohn Birrell } 4301673e404SJohn Birrell 4311673e404SJohn Birrell typedef struct resbuf { 4321673e404SJohn Birrell caddr_t rb_base; 4331673e404SJohn Birrell caddr_t rb_ptr; 4341673e404SJohn Birrell size_t rb_size; 4351673e404SJohn Birrell z_stream rb_zstr; 4361673e404SJohn Birrell } resbuf_t; 4371673e404SJohn Birrell 4381673e404SJohn Birrell static void 4391673e404SJohn Birrell rbzs_grow(resbuf_t *rb) 4401673e404SJohn Birrell { 4411673e404SJohn Birrell off_t ptroff = (caddr_t)rb->rb_zstr.next_out - rb->rb_base; 4421673e404SJohn Birrell 4431673e404SJohn Birrell rb->rb_size += RES_BUF_CHUNK_SIZE; 4441673e404SJohn Birrell rb->rb_base = xrealloc(rb->rb_base, rb->rb_size); 4451673e404SJohn Birrell rb->rb_ptr = rb->rb_base + ptroff; 4461673e404SJohn Birrell rb->rb_zstr.next_out = (Bytef *)(rb->rb_ptr); 4471673e404SJohn Birrell rb->rb_zstr.avail_out += RES_BUF_CHUNK_SIZE; 4481673e404SJohn Birrell } 4491673e404SJohn Birrell 4501673e404SJohn Birrell static void 4511673e404SJohn Birrell compress_start(resbuf_t *rb) 4521673e404SJohn Birrell { 4531673e404SJohn Birrell int rc; 4541673e404SJohn Birrell 4551673e404SJohn Birrell rb->rb_zstr.zalloc = (alloc_func)0; 4561673e404SJohn Birrell rb->rb_zstr.zfree = (free_func)0; 4571673e404SJohn Birrell rb->rb_zstr.opaque = (voidpf)0; 4581673e404SJohn Birrell 4591673e404SJohn Birrell if ((rc = deflateInit(&rb->rb_zstr, Z_BEST_COMPRESSION)) != Z_OK) 4601673e404SJohn Birrell parseterminate("zlib start failed: %s", zError(rc)); 4611673e404SJohn Birrell } 4621673e404SJohn Birrell 4631673e404SJohn Birrell static ssize_t 4644cc75139SJohn Birrell compress_buffer(void *buf, size_t n, void *data) 4651673e404SJohn Birrell { 4661673e404SJohn Birrell resbuf_t *rb = (resbuf_t *)data; 4671673e404SJohn Birrell int rc; 4681673e404SJohn Birrell 4691673e404SJohn Birrell rb->rb_zstr.next_out = (Bytef *)rb->rb_ptr; 4701673e404SJohn Birrell rb->rb_zstr.avail_out = rb->rb_size - (rb->rb_ptr - rb->rb_base); 4714cc75139SJohn Birrell rb->rb_zstr.next_in = buf; 4721673e404SJohn Birrell rb->rb_zstr.avail_in = n; 4731673e404SJohn Birrell 4741673e404SJohn Birrell while (rb->rb_zstr.avail_in) { 4751673e404SJohn Birrell if (rb->rb_zstr.avail_out == 0) 4761673e404SJohn Birrell rbzs_grow(rb); 4771673e404SJohn Birrell 4781673e404SJohn Birrell if ((rc = deflate(&rb->rb_zstr, Z_NO_FLUSH)) != Z_OK) 4791673e404SJohn Birrell parseterminate("zlib deflate failed: %s", zError(rc)); 4801673e404SJohn Birrell } 4811673e404SJohn Birrell rb->rb_ptr = (caddr_t)rb->rb_zstr.next_out; 4821673e404SJohn Birrell 4831673e404SJohn Birrell return (n); 4841673e404SJohn Birrell } 4851673e404SJohn Birrell 4861673e404SJohn Birrell static void 4871673e404SJohn Birrell compress_flush(resbuf_t *rb, int type) 4881673e404SJohn Birrell { 4891673e404SJohn Birrell int rc; 4901673e404SJohn Birrell 4911673e404SJohn Birrell for (;;) { 4921673e404SJohn Birrell if (rb->rb_zstr.avail_out == 0) 4931673e404SJohn Birrell rbzs_grow(rb); 4941673e404SJohn Birrell 4951673e404SJohn Birrell rc = deflate(&rb->rb_zstr, type); 4961673e404SJohn Birrell if ((type == Z_FULL_FLUSH && rc == Z_BUF_ERROR) || 4971673e404SJohn Birrell (type == Z_FINISH && rc == Z_STREAM_END)) 4981673e404SJohn Birrell break; 4991673e404SJohn Birrell else if (rc != Z_OK) 5001673e404SJohn Birrell parseterminate("zlib finish failed: %s", zError(rc)); 5011673e404SJohn Birrell } 5021673e404SJohn Birrell rb->rb_ptr = (caddr_t)rb->rb_zstr.next_out; 5031673e404SJohn Birrell } 5041673e404SJohn Birrell 5051673e404SJohn Birrell static void 5061673e404SJohn Birrell compress_end(resbuf_t *rb) 5071673e404SJohn Birrell { 5081673e404SJohn Birrell int rc; 5091673e404SJohn Birrell 5101673e404SJohn Birrell compress_flush(rb, Z_FINISH); 5111673e404SJohn Birrell 5121673e404SJohn Birrell if ((rc = deflateEnd(&rb->rb_zstr)) != Z_OK) 5131673e404SJohn Birrell parseterminate("zlib end failed: %s", zError(rc)); 5141673e404SJohn Birrell } 5151673e404SJohn Birrell 5161673e404SJohn Birrell /* 5171673e404SJohn Birrell * Pad the buffer to a power-of-2 boundary 5181673e404SJohn Birrell */ 5191673e404SJohn Birrell static void 5201673e404SJohn Birrell pad_buffer(ctf_buf_t *buf, int align) 5211673e404SJohn Birrell { 5221673e404SJohn Birrell uint_t cur = ctf_buf_cur(buf); 5231673e404SJohn Birrell ssize_t topad = (align - (cur % align)) % align; 5241673e404SJohn Birrell static const char pad[8] = { 0 }; 5251673e404SJohn Birrell 5261673e404SJohn Birrell while (topad > 0) { 5271673e404SJohn Birrell ctf_buf_write(buf, pad, (topad > 8 ? 8 : topad)); 5281673e404SJohn Birrell topad -= 8; 5291673e404SJohn Birrell } 5301673e404SJohn Birrell } 5311673e404SJohn Birrell 5321673e404SJohn Birrell static ssize_t 5334cc75139SJohn Birrell bcopy_data(void *buf, size_t n, void *data) 5341673e404SJohn Birrell { 5351673e404SJohn Birrell caddr_t *posp = (caddr_t *)data; 5361673e404SJohn Birrell bcopy(buf, *posp, n); 5371673e404SJohn Birrell *posp += n; 5381673e404SJohn Birrell return (n); 5391673e404SJohn Birrell } 5401673e404SJohn Birrell 5411673e404SJohn Birrell static caddr_t 5421673e404SJohn Birrell write_buffer(ctf_header_t *h, ctf_buf_t *buf, size_t *resszp) 5431673e404SJohn Birrell { 5441673e404SJohn Birrell caddr_t outbuf; 5451673e404SJohn Birrell caddr_t bufpos; 5461673e404SJohn Birrell 5471673e404SJohn Birrell outbuf = xmalloc(sizeof (ctf_header_t) + (buf->ctb_ptr - buf->ctb_base) 5481673e404SJohn Birrell + buf->ctb_strtab.str_size); 5491673e404SJohn Birrell 5501673e404SJohn Birrell bufpos = outbuf; 5511673e404SJohn Birrell (void) bcopy_data(h, sizeof (ctf_header_t), &bufpos); 5521673e404SJohn Birrell (void) bcopy_data(buf->ctb_base, buf->ctb_ptr - buf->ctb_base, 5531673e404SJohn Birrell &bufpos); 5541673e404SJohn Birrell (void) strtab_write(&buf->ctb_strtab, bcopy_data, &bufpos); 5551673e404SJohn Birrell *resszp = bufpos - outbuf; 5561673e404SJohn Birrell return (outbuf); 5571673e404SJohn Birrell } 5581673e404SJohn Birrell 5591673e404SJohn Birrell /* 5601673e404SJohn Birrell * Create the compression buffer, and fill it with the CTF and string 5611673e404SJohn Birrell * table data. We flush the compression state between the two so the 5621673e404SJohn Birrell * dictionary used for the string tables won't be polluted with values 5631673e404SJohn Birrell * that made sense for the CTF data. 5641673e404SJohn Birrell */ 5651673e404SJohn Birrell static caddr_t 5661673e404SJohn Birrell write_compressed_buffer(ctf_header_t *h, ctf_buf_t *buf, size_t *resszp) 5671673e404SJohn Birrell { 5681673e404SJohn Birrell resbuf_t resbuf; 5691673e404SJohn Birrell resbuf.rb_size = RES_BUF_CHUNK_SIZE; 5701673e404SJohn Birrell resbuf.rb_base = xmalloc(resbuf.rb_size); 5711673e404SJohn Birrell bcopy(h, resbuf.rb_base, sizeof (ctf_header_t)); 5721673e404SJohn Birrell resbuf.rb_ptr = resbuf.rb_base + sizeof (ctf_header_t); 5731673e404SJohn Birrell 5741673e404SJohn Birrell compress_start(&resbuf); 5751673e404SJohn Birrell (void) compress_buffer(buf->ctb_base, buf->ctb_ptr - buf->ctb_base, 5761673e404SJohn Birrell &resbuf); 5771673e404SJohn Birrell compress_flush(&resbuf, Z_FULL_FLUSH); 5781673e404SJohn Birrell (void) strtab_write(&buf->ctb_strtab, compress_buffer, &resbuf); 5791673e404SJohn Birrell compress_end(&resbuf); 5801673e404SJohn Birrell 5811673e404SJohn Birrell *resszp = (resbuf.rb_ptr - resbuf.rb_base); 5821673e404SJohn Birrell return (resbuf.rb_base); 5831673e404SJohn Birrell } 5841673e404SJohn Birrell 5851673e404SJohn Birrell caddr_t 5861673e404SJohn Birrell ctf_gen(iiburst_t *iiburst, size_t *resszp, int do_compress) 5871673e404SJohn Birrell { 5881673e404SJohn Birrell ctf_buf_t *buf = ctf_buf_new(); 5891673e404SJohn Birrell ctf_header_t h; 5901673e404SJohn Birrell caddr_t outbuf; 5911673e404SJohn Birrell 5921673e404SJohn Birrell int i; 5931673e404SJohn Birrell 5941673e404SJohn Birrell /* 5951673e404SJohn Birrell * Prepare the header, and create the CTF output buffers. The data 5961673e404SJohn Birrell * object section and function section are both lists of 2-byte 5971673e404SJohn Birrell * integers; we pad these out to the next 4-byte boundary if needed. 5981673e404SJohn Birrell */ 5991673e404SJohn Birrell h.cth_magic = CTF_MAGIC; 6001673e404SJohn Birrell h.cth_version = CTF_VERSION; 6011673e404SJohn Birrell h.cth_flags = do_compress ? CTF_F_COMPRESS : 0; 6021673e404SJohn Birrell h.cth_parlabel = strtab_insert(&buf->ctb_strtab, 6031673e404SJohn Birrell iiburst->iib_td->td_parlabel); 6041673e404SJohn Birrell h.cth_parname = strtab_insert(&buf->ctb_strtab, 6051673e404SJohn Birrell iiburst->iib_td->td_parname); 6061673e404SJohn Birrell 6071673e404SJohn Birrell h.cth_lbloff = 0; 6084cc75139SJohn Birrell (void) list_iter(iiburst->iib_td->td_labels, write_label, 6091673e404SJohn Birrell buf); 6101673e404SJohn Birrell 6111673e404SJohn Birrell pad_buffer(buf, 2); 6121673e404SJohn Birrell h.cth_objtoff = ctf_buf_cur(buf); 6131673e404SJohn Birrell for (i = 0; i < iiburst->iib_nobjts; i++) 6141673e404SJohn Birrell write_objects(iiburst->iib_objts[i], buf); 6151673e404SJohn Birrell 6161673e404SJohn Birrell pad_buffer(buf, 2); 6171673e404SJohn Birrell h.cth_funcoff = ctf_buf_cur(buf); 6181673e404SJohn Birrell for (i = 0; i < iiburst->iib_nfuncs; i++) 6191673e404SJohn Birrell write_functions(iiburst->iib_funcs[i], buf); 6201673e404SJohn Birrell 6211673e404SJohn Birrell pad_buffer(buf, 4); 6221673e404SJohn Birrell h.cth_typeoff = ctf_buf_cur(buf); 6234cc75139SJohn Birrell (void) list_iter(iiburst->iib_types, write_type, buf); 6241673e404SJohn Birrell 6251673e404SJohn Birrell debug(2, "CTF wrote %d types\n", list_count(iiburst->iib_types)); 6261673e404SJohn Birrell 6271673e404SJohn Birrell h.cth_stroff = ctf_buf_cur(buf); 6281673e404SJohn Birrell h.cth_strlen = strtab_size(&buf->ctb_strtab); 6291673e404SJohn Birrell 6301673e404SJohn Birrell /* 6311673e404SJohn Birrell * We only do compression for ctfmerge, as ctfconvert is only 6321673e404SJohn Birrell * supposed to be used on intermediary build objects. This is 6331673e404SJohn Birrell * significantly faster. 6341673e404SJohn Birrell */ 6351673e404SJohn Birrell if (do_compress) 6361673e404SJohn Birrell outbuf = write_compressed_buffer(&h, buf, resszp); 6371673e404SJohn Birrell else 6381673e404SJohn Birrell outbuf = write_buffer(&h, buf, resszp); 6391673e404SJohn Birrell 6401673e404SJohn Birrell ctf_buf_free(buf); 6411673e404SJohn Birrell return (outbuf); 6421673e404SJohn Birrell } 6431673e404SJohn Birrell 6444cc75139SJohn Birrell static void 6451673e404SJohn Birrell get_ctt_size(ctf_type_t *ctt, size_t *sizep, size_t *incrementp) 6461673e404SJohn Birrell { 6471673e404SJohn Birrell if (ctt->ctt_size == CTF_LSIZE_SENT) { 6481673e404SJohn Birrell *sizep = (size_t)CTF_TYPE_LSIZE(ctt); 6491673e404SJohn Birrell *incrementp = sizeof (ctf_type_t); 6501673e404SJohn Birrell } else { 6511673e404SJohn Birrell *sizep = ctt->ctt_size; 6521673e404SJohn Birrell *incrementp = sizeof (ctf_stype_t); 6531673e404SJohn Birrell } 6541673e404SJohn Birrell } 6551673e404SJohn Birrell 6561673e404SJohn Birrell static int 6571673e404SJohn Birrell count_types(ctf_header_t *h, caddr_t data) 6581673e404SJohn Birrell { 6591673e404SJohn Birrell caddr_t dptr = data + h->cth_typeoff; 6601673e404SJohn Birrell int count = 0; 6611673e404SJohn Birrell 6621673e404SJohn Birrell dptr = data + h->cth_typeoff; 6631673e404SJohn Birrell while (dptr < data + h->cth_stroff) { 6644cc75139SJohn Birrell void *v = (void *) dptr; 6654cc75139SJohn Birrell ctf_type_t *ctt = v; 6661673e404SJohn Birrell size_t vlen = CTF_INFO_VLEN(ctt->ctt_info); 6671673e404SJohn Birrell size_t size, increment; 6681673e404SJohn Birrell 6691673e404SJohn Birrell get_ctt_size(ctt, &size, &increment); 6701673e404SJohn Birrell 6711673e404SJohn Birrell switch (CTF_INFO_KIND(ctt->ctt_info)) { 6721673e404SJohn Birrell case CTF_K_INTEGER: 6731673e404SJohn Birrell case CTF_K_FLOAT: 6741673e404SJohn Birrell dptr += 4; 6751673e404SJohn Birrell break; 6761673e404SJohn Birrell case CTF_K_POINTER: 6771673e404SJohn Birrell case CTF_K_FORWARD: 6781673e404SJohn Birrell case CTF_K_TYPEDEF: 6791673e404SJohn Birrell case CTF_K_VOLATILE: 6801673e404SJohn Birrell case CTF_K_CONST: 6811673e404SJohn Birrell case CTF_K_RESTRICT: 6821673e404SJohn Birrell case CTF_K_FUNCTION: 6831673e404SJohn Birrell dptr += sizeof (ushort_t) * (vlen + (vlen & 1)); 6841673e404SJohn Birrell break; 6851673e404SJohn Birrell case CTF_K_ARRAY: 6861673e404SJohn Birrell dptr += sizeof (ctf_array_t); 6871673e404SJohn Birrell break; 6881673e404SJohn Birrell case CTF_K_STRUCT: 6891673e404SJohn Birrell case CTF_K_UNION: 6901673e404SJohn Birrell if (size < CTF_LSTRUCT_THRESH) 6911673e404SJohn Birrell dptr += sizeof (ctf_member_t) * vlen; 6921673e404SJohn Birrell else 6931673e404SJohn Birrell dptr += sizeof (ctf_lmember_t) * vlen; 6941673e404SJohn Birrell break; 6951673e404SJohn Birrell case CTF_K_ENUM: 6961673e404SJohn Birrell dptr += sizeof (ctf_enum_t) * vlen; 6971673e404SJohn Birrell break; 6981673e404SJohn Birrell case CTF_K_UNKNOWN: 6991673e404SJohn Birrell break; 7001673e404SJohn Birrell default: 7011673e404SJohn Birrell parseterminate("Unknown CTF type %d (#%d) at %#x", 7021673e404SJohn Birrell CTF_INFO_KIND(ctt->ctt_info), count, dptr - data); 7031673e404SJohn Birrell } 7041673e404SJohn Birrell 7051673e404SJohn Birrell dptr += increment; 7061673e404SJohn Birrell count++; 7071673e404SJohn Birrell } 7081673e404SJohn Birrell 7091673e404SJohn Birrell debug(3, "CTF read %d types\n", count); 7101673e404SJohn Birrell 7111673e404SJohn Birrell return (count); 7121673e404SJohn Birrell } 7131673e404SJohn Birrell 7141673e404SJohn Birrell /* 7151673e404SJohn Birrell * Resurrect the labels stored in the CTF data, returning the index associated 7161673e404SJohn Birrell * with a label provided by the caller. There are several cases, outlined 7171673e404SJohn Birrell * below. Note that, given two labels, the one associated with the lesser type 7181673e404SJohn Birrell * index is considered to be older than the other. 7191673e404SJohn Birrell * 7201673e404SJohn Birrell * 1. matchlbl == NULL - return the index of the most recent label. 7211673e404SJohn Birrell * 2. matchlbl == "BASE" - return the index of the oldest label. 7221673e404SJohn Birrell * 3. matchlbl != NULL, but doesn't match any labels in the section - warn 7231673e404SJohn Birrell * the user, and proceed as if matchlbl == "BASE" (for safety). 7241673e404SJohn Birrell * 4. matchlbl != NULL, and matches one of the labels in the section - return 7251673e404SJohn Birrell * the type index associated with the label. 7261673e404SJohn Birrell */ 7271673e404SJohn Birrell static int 7281673e404SJohn Birrell resurrect_labels(ctf_header_t *h, tdata_t *td, caddr_t ctfdata, char *matchlbl) 7291673e404SJohn Birrell { 7301673e404SJohn Birrell caddr_t buf = ctfdata + h->cth_lbloff; 7311673e404SJohn Birrell caddr_t sbuf = ctfdata + h->cth_stroff; 7321673e404SJohn Birrell size_t bufsz = h->cth_objtoff - h->cth_lbloff; 7331673e404SJohn Birrell int lastidx = 0, baseidx = -1; 7344cc75139SJohn Birrell char *baselabel = NULL; 7351673e404SJohn Birrell ctf_lblent_t *ctl; 7364cc75139SJohn Birrell void *v = (void *) buf; 7371673e404SJohn Birrell 7384cc75139SJohn Birrell for (ctl = v; (caddr_t)ctl < buf + bufsz; ctl++) { 7391673e404SJohn Birrell char *label = sbuf + ctl->ctl_label; 7401673e404SJohn Birrell 7411673e404SJohn Birrell lastidx = ctl->ctl_typeidx; 7421673e404SJohn Birrell 7431673e404SJohn Birrell debug(3, "Resurrected label %s type idx %d\n", label, lastidx); 7441673e404SJohn Birrell 7451673e404SJohn Birrell tdata_label_add(td, label, lastidx); 7461673e404SJohn Birrell 7471673e404SJohn Birrell if (baseidx == -1) { 7481673e404SJohn Birrell baseidx = lastidx; 7491673e404SJohn Birrell baselabel = label; 7501673e404SJohn Birrell if (matchlbl != NULL && streq(matchlbl, "BASE")) 7511673e404SJohn Birrell return (lastidx); 7521673e404SJohn Birrell } 7531673e404SJohn Birrell 7541673e404SJohn Birrell if (matchlbl != NULL && streq(label, matchlbl)) 7551673e404SJohn Birrell return (lastidx); 7561673e404SJohn Birrell } 7571673e404SJohn Birrell 7581673e404SJohn Birrell if (matchlbl != NULL) { 7591673e404SJohn Birrell /* User provided a label that didn't match */ 7601673e404SJohn Birrell warning("%s: Cannot find label `%s' - using base (%s)\n", 7611673e404SJohn Birrell curfile, matchlbl, (baselabel ? baselabel : "NONE")); 7621673e404SJohn Birrell 7631673e404SJohn Birrell tdata_label_free(td); 7641673e404SJohn Birrell tdata_label_add(td, baselabel, baseidx); 7651673e404SJohn Birrell 7661673e404SJohn Birrell return (baseidx); 7671673e404SJohn Birrell } 7681673e404SJohn Birrell 7691673e404SJohn Birrell return (lastidx); 7701673e404SJohn Birrell } 7711673e404SJohn Birrell 7721673e404SJohn Birrell static void 7731673e404SJohn Birrell resurrect_objects(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize, 7741673e404SJohn Birrell caddr_t ctfdata, symit_data_t *si) 7751673e404SJohn Birrell { 7761673e404SJohn Birrell caddr_t buf = ctfdata + h->cth_objtoff; 7771673e404SJohn Birrell size_t bufsz = h->cth_funcoff - h->cth_objtoff; 7781673e404SJohn Birrell caddr_t dptr; 7791673e404SJohn Birrell 7801673e404SJohn Birrell symit_reset(si); 7811673e404SJohn Birrell for (dptr = buf; dptr < buf + bufsz; dptr += 2) { 7824cc75139SJohn Birrell void *v = (void *) dptr; 7834cc75139SJohn Birrell ushort_t id = *((ushort_t *)v); 7841673e404SJohn Birrell iidesc_t *ii; 7851673e404SJohn Birrell GElf_Sym *sym; 7861673e404SJohn Birrell 7871673e404SJohn Birrell if (!(sym = symit_next(si, STT_OBJECT)) && id != 0) { 7881673e404SJohn Birrell parseterminate( 7891673e404SJohn Birrell "Unexpected end of object symbols at %x of %x", 7901673e404SJohn Birrell dptr - buf, bufsz); 7911673e404SJohn Birrell } 7921673e404SJohn Birrell 7931673e404SJohn Birrell if (id == 0) { 7941673e404SJohn Birrell debug(3, "Skipping null object\n"); 7951673e404SJohn Birrell continue; 7961673e404SJohn Birrell } else if (id >= tdsize) { 7971673e404SJohn Birrell parseterminate("Reference to invalid type %d", id); 7981673e404SJohn Birrell } 7991673e404SJohn Birrell 8001673e404SJohn Birrell ii = iidesc_new(symit_name(si)); 8011673e404SJohn Birrell ii->ii_dtype = tdarr[id]; 8021673e404SJohn Birrell if (GELF_ST_BIND(sym->st_info) == STB_LOCAL) { 8031673e404SJohn Birrell ii->ii_type = II_SVAR; 8041673e404SJohn Birrell ii->ii_owner = xstrdup(symit_curfile(si)); 8051673e404SJohn Birrell } else 8061673e404SJohn Birrell ii->ii_type = II_GVAR; 8071673e404SJohn Birrell hash_add(td->td_iihash, ii); 8081673e404SJohn Birrell 8091673e404SJohn Birrell debug(3, "Resurrected %s object %s (%d) from %s\n", 8101673e404SJohn Birrell (ii->ii_type == II_GVAR ? "global" : "static"), 8111673e404SJohn Birrell ii->ii_name, id, (ii->ii_owner ? ii->ii_owner : "(none)")); 8121673e404SJohn Birrell } 8131673e404SJohn Birrell } 8141673e404SJohn Birrell 8151673e404SJohn Birrell static void 8161673e404SJohn Birrell resurrect_functions(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize, 8171673e404SJohn Birrell caddr_t ctfdata, symit_data_t *si) 8181673e404SJohn Birrell { 8191673e404SJohn Birrell caddr_t buf = ctfdata + h->cth_funcoff; 8201673e404SJohn Birrell size_t bufsz = h->cth_typeoff - h->cth_funcoff; 8211673e404SJohn Birrell caddr_t dptr = buf; 8221673e404SJohn Birrell iidesc_t *ii; 8231673e404SJohn Birrell ushort_t info; 8241673e404SJohn Birrell ushort_t retid; 8251673e404SJohn Birrell GElf_Sym *sym; 8261673e404SJohn Birrell int i; 8271673e404SJohn Birrell 8281673e404SJohn Birrell symit_reset(si); 8291673e404SJohn Birrell while (dptr < buf + bufsz) { 8304cc75139SJohn Birrell void *v = (void *) dptr; 8314cc75139SJohn Birrell info = *((ushort_t *)v); 8321673e404SJohn Birrell dptr += 2; 8331673e404SJohn Birrell 8341673e404SJohn Birrell if (!(sym = symit_next(si, STT_FUNC)) && info != 0) 8351673e404SJohn Birrell parseterminate("Unexpected end of function symbols"); 8361673e404SJohn Birrell 8371673e404SJohn Birrell if (info == 0) { 8381673e404SJohn Birrell debug(3, "Skipping null function (%s)\n", 8391673e404SJohn Birrell symit_name(si)); 8401673e404SJohn Birrell continue; 8411673e404SJohn Birrell } 8421673e404SJohn Birrell 8434cc75139SJohn Birrell v = (void *) dptr; 8444cc75139SJohn Birrell retid = *((ushort_t *)v); 8451673e404SJohn Birrell dptr += 2; 8461673e404SJohn Birrell 8471673e404SJohn Birrell if (retid >= tdsize) 8481673e404SJohn Birrell parseterminate("Reference to invalid type %d", retid); 8491673e404SJohn Birrell 8501673e404SJohn Birrell ii = iidesc_new(symit_name(si)); 8511673e404SJohn Birrell ii->ii_dtype = tdarr[retid]; 8521673e404SJohn Birrell if (GELF_ST_BIND(sym->st_info) == STB_LOCAL) { 8531673e404SJohn Birrell ii->ii_type = II_SFUN; 8541673e404SJohn Birrell ii->ii_owner = xstrdup(symit_curfile(si)); 8551673e404SJohn Birrell } else 8561673e404SJohn Birrell ii->ii_type = II_GFUN; 8571673e404SJohn Birrell ii->ii_nargs = CTF_INFO_VLEN(info); 8581673e404SJohn Birrell if (ii->ii_nargs) 8591673e404SJohn Birrell ii->ii_args = 8601673e404SJohn Birrell xmalloc(sizeof (tdesc_t *) * ii->ii_nargs); 8611673e404SJohn Birrell 8621673e404SJohn Birrell for (i = 0; i < ii->ii_nargs; i++, dptr += 2) { 8634cc75139SJohn Birrell v = (void *) dptr; 8644cc75139SJohn Birrell ushort_t id = *((ushort_t *)v); 8651673e404SJohn Birrell if (id >= tdsize) 8661673e404SJohn Birrell parseterminate("Reference to invalid type %d", 8671673e404SJohn Birrell id); 8681673e404SJohn Birrell ii->ii_args[i] = tdarr[id]; 8691673e404SJohn Birrell } 8701673e404SJohn Birrell 8711673e404SJohn Birrell if (ii->ii_nargs && ii->ii_args[ii->ii_nargs - 1] == NULL) { 8721673e404SJohn Birrell ii->ii_nargs--; 8731673e404SJohn Birrell ii->ii_vargs = 1; 8741673e404SJohn Birrell } 8751673e404SJohn Birrell 8761673e404SJohn Birrell hash_add(td->td_iihash, ii); 8771673e404SJohn Birrell 8781673e404SJohn Birrell debug(3, "Resurrected %s function %s (%d, %d args)\n", 8791673e404SJohn Birrell (ii->ii_type == II_GFUN ? "global" : "static"), 8801673e404SJohn Birrell ii->ii_name, retid, ii->ii_nargs); 8811673e404SJohn Birrell } 8821673e404SJohn Birrell } 8831673e404SJohn Birrell 8841673e404SJohn Birrell static void 8851673e404SJohn Birrell resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize, 8861673e404SJohn Birrell caddr_t ctfdata, int maxid) 8871673e404SJohn Birrell { 8881673e404SJohn Birrell caddr_t buf = ctfdata + h->cth_typeoff; 8891673e404SJohn Birrell size_t bufsz = h->cth_stroff - h->cth_typeoff; 8901673e404SJohn Birrell caddr_t sbuf = ctfdata + h->cth_stroff; 8911673e404SJohn Birrell caddr_t dptr = buf; 8921673e404SJohn Birrell tdesc_t *tdp; 8931673e404SJohn Birrell uint_t data; 8941673e404SJohn Birrell uint_t encoding; 8951673e404SJohn Birrell size_t size, increment; 8961673e404SJohn Birrell int tcnt; 8971673e404SJohn Birrell int iicnt = 0; 8981673e404SJohn Birrell tid_t tid, argid; 8991673e404SJohn Birrell int kind, vlen; 9001673e404SJohn Birrell int i; 9011673e404SJohn Birrell 9021673e404SJohn Birrell elist_t **epp; 9031673e404SJohn Birrell mlist_t **mpp; 9041673e404SJohn Birrell intr_t *ip; 9051673e404SJohn Birrell 9061673e404SJohn Birrell ctf_type_t *ctt; 9071673e404SJohn Birrell ctf_array_t *cta; 9081673e404SJohn Birrell ctf_enum_t *cte; 9091673e404SJohn Birrell 9101673e404SJohn Birrell /* 9111673e404SJohn Birrell * A maxid of zero indicates a request to resurrect all types, so reset 9121673e404SJohn Birrell * maxid to the maximum type id. 9131673e404SJohn Birrell */ 9141673e404SJohn Birrell if (maxid == 0) 9151673e404SJohn Birrell maxid = CTF_MAX_TYPE; 9161673e404SJohn Birrell 9171673e404SJohn Birrell for (dptr = buf, tcnt = 0, tid = 1; dptr < buf + bufsz; tcnt++, tid++) { 9181673e404SJohn Birrell if (tid > maxid) 9191673e404SJohn Birrell break; 9201673e404SJohn Birrell 9211673e404SJohn Birrell if (tid >= tdsize) 9221673e404SJohn Birrell parseterminate("Reference to invalid type %d", tid); 9231673e404SJohn Birrell 9244cc75139SJohn Birrell void *v = (void *) dptr; 9254cc75139SJohn Birrell ctt = v; 9261673e404SJohn Birrell 9271673e404SJohn Birrell get_ctt_size(ctt, &size, &increment); 9281673e404SJohn Birrell dptr += increment; 9291673e404SJohn Birrell 9301673e404SJohn Birrell tdp = tdarr[tid]; 9311673e404SJohn Birrell 9321673e404SJohn Birrell if (CTF_NAME_STID(ctt->ctt_name) != CTF_STRTAB_0) 9331673e404SJohn Birrell parseterminate( 9341673e404SJohn Birrell "Unable to cope with non-zero strtab id"); 9351673e404SJohn Birrell if (CTF_NAME_OFFSET(ctt->ctt_name) != 0) { 9361673e404SJohn Birrell tdp->t_name = 9371673e404SJohn Birrell xstrdup(sbuf + CTF_NAME_OFFSET(ctt->ctt_name)); 9381673e404SJohn Birrell } else 9391673e404SJohn Birrell tdp->t_name = NULL; 9401673e404SJohn Birrell 9411673e404SJohn Birrell kind = CTF_INFO_KIND(ctt->ctt_info); 9421673e404SJohn Birrell vlen = CTF_INFO_VLEN(ctt->ctt_info); 9431673e404SJohn Birrell 9441673e404SJohn Birrell switch (kind) { 9451673e404SJohn Birrell case CTF_K_INTEGER: 9461673e404SJohn Birrell tdp->t_type = INTRINSIC; 9471673e404SJohn Birrell tdp->t_size = size; 9481673e404SJohn Birrell 9494cc75139SJohn Birrell v = (void *) dptr; 9504cc75139SJohn Birrell data = *((uint_t *)v); 9511673e404SJohn Birrell dptr += sizeof (uint_t); 9521673e404SJohn Birrell encoding = CTF_INT_ENCODING(data); 9531673e404SJohn Birrell 9541673e404SJohn Birrell ip = xmalloc(sizeof (intr_t)); 9551673e404SJohn Birrell ip->intr_type = INTR_INT; 9561673e404SJohn Birrell ip->intr_signed = (encoding & CTF_INT_SIGNED) ? 1 : 0; 9571673e404SJohn Birrell 9581673e404SJohn Birrell if (encoding & CTF_INT_CHAR) 9591673e404SJohn Birrell ip->intr_iformat = 'c'; 9601673e404SJohn Birrell else if (encoding & CTF_INT_BOOL) 9611673e404SJohn Birrell ip->intr_iformat = 'b'; 9621673e404SJohn Birrell else if (encoding & CTF_INT_VARARGS) 9631673e404SJohn Birrell ip->intr_iformat = 'v'; 9641673e404SJohn Birrell else 9651673e404SJohn Birrell ip->intr_iformat = '\0'; 9661673e404SJohn Birrell 9671673e404SJohn Birrell ip->intr_offset = CTF_INT_OFFSET(data); 9681673e404SJohn Birrell ip->intr_nbits = CTF_INT_BITS(data); 9691673e404SJohn Birrell tdp->t_intr = ip; 9701673e404SJohn Birrell break; 9711673e404SJohn Birrell 9721673e404SJohn Birrell case CTF_K_FLOAT: 9731673e404SJohn Birrell tdp->t_type = INTRINSIC; 9741673e404SJohn Birrell tdp->t_size = size; 9751673e404SJohn Birrell 9764cc75139SJohn Birrell v = (void *) dptr; 9774cc75139SJohn Birrell data = *((uint_t *)v); 9781673e404SJohn Birrell dptr += sizeof (uint_t); 9791673e404SJohn Birrell 9801673e404SJohn Birrell ip = xcalloc(sizeof (intr_t)); 9811673e404SJohn Birrell ip->intr_type = INTR_REAL; 9821673e404SJohn Birrell ip->intr_fformat = CTF_FP_ENCODING(data); 9831673e404SJohn Birrell ip->intr_offset = CTF_FP_OFFSET(data); 9841673e404SJohn Birrell ip->intr_nbits = CTF_FP_BITS(data); 9851673e404SJohn Birrell tdp->t_intr = ip; 9861673e404SJohn Birrell break; 9871673e404SJohn Birrell 9881673e404SJohn Birrell case CTF_K_POINTER: 9891673e404SJohn Birrell tdp->t_type = POINTER; 9901673e404SJohn Birrell tdp->t_tdesc = tdarr[ctt->ctt_type]; 9911673e404SJohn Birrell break; 9921673e404SJohn Birrell 9931673e404SJohn Birrell case CTF_K_ARRAY: 9941673e404SJohn Birrell tdp->t_type = ARRAY; 9951673e404SJohn Birrell tdp->t_size = size; 9961673e404SJohn Birrell 9974cc75139SJohn Birrell v = (void *) dptr; 9984cc75139SJohn Birrell cta = v; 9991673e404SJohn Birrell dptr += sizeof (ctf_array_t); 10001673e404SJohn Birrell 10011673e404SJohn Birrell tdp->t_ardef = xmalloc(sizeof (ardef_t)); 10021673e404SJohn Birrell tdp->t_ardef->ad_contents = tdarr[cta->cta_contents]; 10031673e404SJohn Birrell tdp->t_ardef->ad_idxtype = tdarr[cta->cta_index]; 10041673e404SJohn Birrell tdp->t_ardef->ad_nelems = cta->cta_nelems; 10051673e404SJohn Birrell break; 10061673e404SJohn Birrell 10071673e404SJohn Birrell case CTF_K_STRUCT: 10081673e404SJohn Birrell case CTF_K_UNION: 10091673e404SJohn Birrell tdp->t_type = (kind == CTF_K_STRUCT ? STRUCT : UNION); 10101673e404SJohn Birrell tdp->t_size = size; 10111673e404SJohn Birrell 10121673e404SJohn Birrell if (size < CTF_LSTRUCT_THRESH) { 10131673e404SJohn Birrell for (i = 0, mpp = &tdp->t_members; i < vlen; 10141673e404SJohn Birrell i++, mpp = &((*mpp)->ml_next)) { 10154cc75139SJohn Birrell v = (void *) dptr; 10164cc75139SJohn Birrell ctf_member_t *ctm = v; 10171673e404SJohn Birrell dptr += sizeof (ctf_member_t); 10181673e404SJohn Birrell 10191673e404SJohn Birrell *mpp = xmalloc(sizeof (mlist_t)); 10201673e404SJohn Birrell (*mpp)->ml_name = xstrdup(sbuf + 10211673e404SJohn Birrell ctm->ctm_name); 10221673e404SJohn Birrell (*mpp)->ml_type = tdarr[ctm->ctm_type]; 10231673e404SJohn Birrell (*mpp)->ml_offset = ctm->ctm_offset; 10241673e404SJohn Birrell (*mpp)->ml_size = 0; 10251673e404SJohn Birrell } 10261673e404SJohn Birrell } else { 10271673e404SJohn Birrell for (i = 0, mpp = &tdp->t_members; i < vlen; 10281673e404SJohn Birrell i++, mpp = &((*mpp)->ml_next)) { 10294cc75139SJohn Birrell v = (void *) dptr; 10304cc75139SJohn Birrell ctf_lmember_t *ctlm = v; 10311673e404SJohn Birrell dptr += sizeof (ctf_lmember_t); 10321673e404SJohn Birrell 10331673e404SJohn Birrell *mpp = xmalloc(sizeof (mlist_t)); 10341673e404SJohn Birrell (*mpp)->ml_name = xstrdup(sbuf + 10351673e404SJohn Birrell ctlm->ctlm_name); 10361673e404SJohn Birrell (*mpp)->ml_type = 10371673e404SJohn Birrell tdarr[ctlm->ctlm_type]; 10381673e404SJohn Birrell (*mpp)->ml_offset = 10391673e404SJohn Birrell (int)CTF_LMEM_OFFSET(ctlm); 10401673e404SJohn Birrell (*mpp)->ml_size = 0; 10411673e404SJohn Birrell } 10421673e404SJohn Birrell } 10431673e404SJohn Birrell 10441673e404SJohn Birrell *mpp = NULL; 10451673e404SJohn Birrell break; 10461673e404SJohn Birrell 10471673e404SJohn Birrell case CTF_K_ENUM: 10481673e404SJohn Birrell tdp->t_type = ENUM; 10491673e404SJohn Birrell tdp->t_size = size; 10501673e404SJohn Birrell 10511673e404SJohn Birrell for (i = 0, epp = &tdp->t_emem; i < vlen; 10521673e404SJohn Birrell i++, epp = &((*epp)->el_next)) { 10534cc75139SJohn Birrell v = (void *) dptr; 10544cc75139SJohn Birrell cte = v; 10551673e404SJohn Birrell dptr += sizeof (ctf_enum_t); 10561673e404SJohn Birrell 10571673e404SJohn Birrell *epp = xmalloc(sizeof (elist_t)); 10581673e404SJohn Birrell (*epp)->el_name = xstrdup(sbuf + cte->cte_name); 10591673e404SJohn Birrell (*epp)->el_number = cte->cte_value; 10601673e404SJohn Birrell } 10611673e404SJohn Birrell *epp = NULL; 10621673e404SJohn Birrell break; 10631673e404SJohn Birrell 10641673e404SJohn Birrell case CTF_K_FORWARD: 10651673e404SJohn Birrell tdp->t_type = FORWARD; 10661673e404SJohn Birrell list_add(&td->td_fwdlist, tdp); 10671673e404SJohn Birrell break; 10681673e404SJohn Birrell 10691673e404SJohn Birrell case CTF_K_TYPEDEF: 10701673e404SJohn Birrell tdp->t_type = TYPEDEF; 10711673e404SJohn Birrell tdp->t_tdesc = tdarr[ctt->ctt_type]; 10721673e404SJohn Birrell break; 10731673e404SJohn Birrell 10741673e404SJohn Birrell case CTF_K_VOLATILE: 10751673e404SJohn Birrell tdp->t_type = VOLATILE; 10761673e404SJohn Birrell tdp->t_tdesc = tdarr[ctt->ctt_type]; 10771673e404SJohn Birrell break; 10781673e404SJohn Birrell 10791673e404SJohn Birrell case CTF_K_CONST: 10801673e404SJohn Birrell tdp->t_type = CONST; 10811673e404SJohn Birrell tdp->t_tdesc = tdarr[ctt->ctt_type]; 10821673e404SJohn Birrell break; 10831673e404SJohn Birrell 10841673e404SJohn Birrell case CTF_K_FUNCTION: 10851673e404SJohn Birrell tdp->t_type = FUNCTION; 10861673e404SJohn Birrell tdp->t_fndef = xcalloc(sizeof (fndef_t)); 10871673e404SJohn Birrell tdp->t_fndef->fn_ret = tdarr[ctt->ctt_type]; 10881673e404SJohn Birrell 10894cc75139SJohn Birrell v = (void *) (dptr + (sizeof (ushort_t) * (vlen - 1))); 10904cc75139SJohn Birrell if (vlen > 0 && *(ushort_t *)v == 0) 10911673e404SJohn Birrell tdp->t_fndef->fn_vargs = 1; 10921673e404SJohn Birrell 10931673e404SJohn Birrell tdp->t_fndef->fn_nargs = vlen - tdp->t_fndef->fn_vargs; 10941673e404SJohn Birrell tdp->t_fndef->fn_args = xcalloc(sizeof (tdesc_t) * 10951673e404SJohn Birrell vlen - tdp->t_fndef->fn_vargs); 10961673e404SJohn Birrell 10971673e404SJohn Birrell for (i = 0; i < vlen; i++) { 10984cc75139SJohn Birrell v = (void *) dptr; 10994cc75139SJohn Birrell argid = *(ushort_t *)v; 11001673e404SJohn Birrell dptr += sizeof (ushort_t); 11011673e404SJohn Birrell 11021673e404SJohn Birrell if (argid != 0) 11031673e404SJohn Birrell tdp->t_fndef->fn_args[i] = tdarr[argid]; 11041673e404SJohn Birrell } 11051673e404SJohn Birrell 11061673e404SJohn Birrell if (vlen & 1) 11071673e404SJohn Birrell dptr += sizeof (ushort_t); 11081673e404SJohn Birrell break; 11091673e404SJohn Birrell 11101673e404SJohn Birrell case CTF_K_RESTRICT: 11111673e404SJohn Birrell tdp->t_type = RESTRICT; 11121673e404SJohn Birrell tdp->t_tdesc = tdarr[ctt->ctt_type]; 11131673e404SJohn Birrell break; 11141673e404SJohn Birrell 11151673e404SJohn Birrell case CTF_K_UNKNOWN: 11161673e404SJohn Birrell break; 11171673e404SJohn Birrell 11181673e404SJohn Birrell default: 11191673e404SJohn Birrell warning("Can't parse unknown CTF type %d\n", kind); 11201673e404SJohn Birrell } 11211673e404SJohn Birrell 11221673e404SJohn Birrell if (CTF_INFO_ISROOT(ctt->ctt_info)) { 11231673e404SJohn Birrell iidesc_t *ii = iidesc_new(tdp->t_name); 11241673e404SJohn Birrell if (tdp->t_type == STRUCT || tdp->t_type == UNION || 11251673e404SJohn Birrell tdp->t_type == ENUM) 11261673e404SJohn Birrell ii->ii_type = II_SOU; 11271673e404SJohn Birrell else 11281673e404SJohn Birrell ii->ii_type = II_TYPE; 11291673e404SJohn Birrell ii->ii_dtype = tdp; 11301673e404SJohn Birrell hash_add(td->td_iihash, ii); 11311673e404SJohn Birrell 11321673e404SJohn Birrell iicnt++; 11331673e404SJohn Birrell } 11341673e404SJohn Birrell 11351673e404SJohn Birrell debug(3, "Resurrected %d %stype %s (%d)\n", tdp->t_type, 11361673e404SJohn Birrell (CTF_INFO_ISROOT(ctt->ctt_info) ? "root " : ""), 11371673e404SJohn Birrell tdesc_name(tdp), tdp->t_id); 11381673e404SJohn Birrell } 11391673e404SJohn Birrell 11401673e404SJohn Birrell debug(3, "Resurrected %d types (%d were roots)\n", tcnt, iicnt); 11411673e404SJohn Birrell } 11421673e404SJohn Birrell 11431673e404SJohn Birrell /* 11441673e404SJohn Birrell * For lack of other inspiration, we're going to take the boring route. We 11451673e404SJohn Birrell * count the number of types. This lets us malloc that many tdesc structs 11461673e404SJohn Birrell * before we start filling them in. This has the advantage of allowing us to 11471673e404SJohn Birrell * avoid a merge-esque remap step. 11481673e404SJohn Birrell */ 11491673e404SJohn Birrell static tdata_t * 11501673e404SJohn Birrell ctf_parse(ctf_header_t *h, caddr_t buf, symit_data_t *si, char *label) 11511673e404SJohn Birrell { 11521673e404SJohn Birrell tdata_t *td = tdata_new(); 11531673e404SJohn Birrell tdesc_t **tdarr; 11541673e404SJohn Birrell int ntypes = count_types(h, buf); 11551673e404SJohn Birrell int idx, i; 11561673e404SJohn Birrell 11571673e404SJohn Birrell /* shudder */ 11581673e404SJohn Birrell tdarr = xcalloc(sizeof (tdesc_t *) * (ntypes + 1)); 11591673e404SJohn Birrell tdarr[0] = NULL; 11601673e404SJohn Birrell for (i = 1; i <= ntypes; i++) { 11611673e404SJohn Birrell tdarr[i] = xcalloc(sizeof (tdesc_t)); 11621673e404SJohn Birrell tdarr[i]->t_id = i; 11631673e404SJohn Birrell } 11641673e404SJohn Birrell 11651673e404SJohn Birrell td->td_parlabel = xstrdup(buf + h->cth_stroff + h->cth_parlabel); 11661673e404SJohn Birrell 11671673e404SJohn Birrell /* we have the technology - we can rebuild them */ 11681673e404SJohn Birrell idx = resurrect_labels(h, td, buf, label); 11691673e404SJohn Birrell 11701673e404SJohn Birrell resurrect_objects(h, td, tdarr, ntypes + 1, buf, si); 11711673e404SJohn Birrell resurrect_functions(h, td, tdarr, ntypes + 1, buf, si); 11721673e404SJohn Birrell resurrect_types(h, td, tdarr, ntypes + 1, buf, idx); 11731673e404SJohn Birrell 11741673e404SJohn Birrell free(tdarr); 11751673e404SJohn Birrell 11761673e404SJohn Birrell td->td_nextid = ntypes + 1; 11771673e404SJohn Birrell 11781673e404SJohn Birrell return (td); 11791673e404SJohn Birrell } 11801673e404SJohn Birrell 11811673e404SJohn Birrell static size_t 11821673e404SJohn Birrell decompress_ctf(caddr_t cbuf, size_t cbufsz, caddr_t dbuf, size_t dbufsz) 11831673e404SJohn Birrell { 11841673e404SJohn Birrell z_stream zstr; 11851673e404SJohn Birrell int rc; 11861673e404SJohn Birrell 11871673e404SJohn Birrell zstr.zalloc = (alloc_func)0; 11881673e404SJohn Birrell zstr.zfree = (free_func)0; 11891673e404SJohn Birrell zstr.opaque = (voidpf)0; 11901673e404SJohn Birrell 11911673e404SJohn Birrell zstr.next_in = (Bytef *)cbuf; 11921673e404SJohn Birrell zstr.avail_in = cbufsz; 11931673e404SJohn Birrell zstr.next_out = (Bytef *)dbuf; 11941673e404SJohn Birrell zstr.avail_out = dbufsz; 11951673e404SJohn Birrell 11961673e404SJohn Birrell if ((rc = inflateInit(&zstr)) != Z_OK || 11971673e404SJohn Birrell (rc = inflate(&zstr, Z_NO_FLUSH)) != Z_STREAM_END || 11981673e404SJohn Birrell (rc = inflateEnd(&zstr)) != Z_OK) { 11991673e404SJohn Birrell warning("CTF decompress zlib error %s\n", zError(rc)); 12004cc75139SJohn Birrell return (0); 12011673e404SJohn Birrell } 12021673e404SJohn Birrell 12031673e404SJohn Birrell debug(3, "reflated %lu bytes to %lu, pointer at %d\n", 12041673e404SJohn Birrell zstr.total_in, zstr.total_out, (caddr_t)zstr.next_in - cbuf); 12051673e404SJohn Birrell 12061673e404SJohn Birrell return (zstr.total_out); 12071673e404SJohn Birrell } 12081673e404SJohn Birrell 12091673e404SJohn Birrell /* 12101673e404SJohn Birrell * Reconstruct the type tree from a given buffer of CTF data. Only the types 12111673e404SJohn Birrell * up to the type associated with the provided label, inclusive, will be 12121673e404SJohn Birrell * reconstructed. If a NULL label is provided, all types will be reconstructed. 12131673e404SJohn Birrell * 12141673e404SJohn Birrell * This function won't work on files that have been uniquified. 12151673e404SJohn Birrell */ 12161673e404SJohn Birrell tdata_t * 12171673e404SJohn Birrell ctf_load(char *file, caddr_t buf, size_t bufsz, symit_data_t *si, char *label) 12181673e404SJohn Birrell { 12191673e404SJohn Birrell ctf_header_t *h; 12201673e404SJohn Birrell caddr_t ctfdata; 12211673e404SJohn Birrell size_t ctfdatasz; 12221673e404SJohn Birrell tdata_t *td; 12231673e404SJohn Birrell 12241673e404SJohn Birrell curfile = file; 12251673e404SJohn Birrell 12261673e404SJohn Birrell if (bufsz < sizeof (ctf_header_t)) 12271673e404SJohn Birrell parseterminate("Corrupt CTF - short header"); 12281673e404SJohn Birrell 12294cc75139SJohn Birrell void *v = (void *) buf; 12304cc75139SJohn Birrell h = v; 12311673e404SJohn Birrell buf += sizeof (ctf_header_t); 12321673e404SJohn Birrell bufsz -= sizeof (ctf_header_t); 12331673e404SJohn Birrell 12341673e404SJohn Birrell if (h->cth_magic != CTF_MAGIC) 12351673e404SJohn Birrell parseterminate("Corrupt CTF - bad magic 0x%x", h->cth_magic); 12361673e404SJohn Birrell 12371673e404SJohn Birrell if (h->cth_version != CTF_VERSION) 12381673e404SJohn Birrell parseterminate("Unknown CTF version %d", h->cth_version); 12391673e404SJohn Birrell 12401673e404SJohn Birrell ctfdatasz = h->cth_stroff + h->cth_strlen; 12411673e404SJohn Birrell if (h->cth_flags & CTF_F_COMPRESS) { 12421673e404SJohn Birrell size_t actual; 12431673e404SJohn Birrell 12441673e404SJohn Birrell ctfdata = xmalloc(ctfdatasz); 12451673e404SJohn Birrell if ((actual = decompress_ctf(buf, bufsz, ctfdata, ctfdatasz)) != 12461673e404SJohn Birrell ctfdatasz) { 12471673e404SJohn Birrell parseterminate("Corrupt CTF - short decompression " 12481673e404SJohn Birrell "(was %d, expecting %d)", actual, ctfdatasz); 12491673e404SJohn Birrell } 12501673e404SJohn Birrell } else { 12511673e404SJohn Birrell ctfdata = buf; 12521673e404SJohn Birrell ctfdatasz = bufsz; 12531673e404SJohn Birrell } 12541673e404SJohn Birrell 12551673e404SJohn Birrell td = ctf_parse(h, ctfdata, si, label); 12561673e404SJohn Birrell 12571673e404SJohn Birrell if (h->cth_flags & CTF_F_COMPRESS) 12581673e404SJohn Birrell free(ctfdata); 12591673e404SJohn Birrell 12601673e404SJohn Birrell curfile = NULL; 12611673e404SJohn Birrell 12621673e404SJohn Birrell return (td); 12631673e404SJohn Birrell } 1264