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