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 /* 221670a1c2SRui 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 */ 50c0794a84SEd Schouten static 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 */ 61*bdf290cdSMark Johnston uint_t nptent; /* number of processed types */ 621673e404SJohn Birrell }; 631673e404SJohn Birrell 64a6425ab5SOleksandr Tymoshenko /* 65a6425ab5SOleksandr Tymoshenko * Macros to reverse byte order 66a6425ab5SOleksandr Tymoshenko */ 67a6425ab5SOleksandr Tymoshenko #define BSWAP_8(x) ((x) & 0xff) 68a6425ab5SOleksandr Tymoshenko #define BSWAP_16(x) ((BSWAP_8(x) << 8) | BSWAP_8((x) >> 8)) 69a6425ab5SOleksandr Tymoshenko #define BSWAP_32(x) ((BSWAP_16(x) << 16) | BSWAP_16((x) >> 16)) 70a6425ab5SOleksandr Tymoshenko 71a6425ab5SOleksandr Tymoshenko #define SWAP_16(x) (x) = BSWAP_16(x) 72a6425ab5SOleksandr Tymoshenko #define SWAP_32(x) (x) = BSWAP_32(x) 73a6425ab5SOleksandr Tymoshenko 74a6425ab5SOleksandr Tymoshenko static int target_requires_swap; 75a6425ab5SOleksandr Tymoshenko 761673e404SJohn Birrell /*PRINTFLIKE1*/ 771673e404SJohn Birrell static void 784cc75139SJohn Birrell parseterminate(const char *fmt, ...) 791673e404SJohn Birrell { 801673e404SJohn Birrell static char msgbuf[1024]; /* sigh */ 811673e404SJohn Birrell va_list ap; 821673e404SJohn Birrell 831673e404SJohn Birrell va_start(ap, fmt); 841673e404SJohn Birrell vsnprintf(msgbuf, sizeof (msgbuf), fmt, ap); 851673e404SJohn Birrell va_end(ap); 861673e404SJohn Birrell 871673e404SJohn Birrell terminate("%s: %s\n", curfile, msgbuf); 881673e404SJohn Birrell } 891673e404SJohn Birrell 904cc75139SJohn Birrell static void 911673e404SJohn Birrell ctf_buf_grow(ctf_buf_t *b) 921673e404SJohn Birrell { 931673e404SJohn Birrell off_t ptroff = b->ctb_ptr - b->ctb_base; 941673e404SJohn Birrell 951673e404SJohn Birrell b->ctb_size += CTF_BUF_CHUNK_SIZE; 961673e404SJohn Birrell b->ctb_base = xrealloc(b->ctb_base, b->ctb_size); 971673e404SJohn Birrell b->ctb_end = b->ctb_base + b->ctb_size; 981673e404SJohn Birrell b->ctb_ptr = b->ctb_base + ptroff; 991673e404SJohn Birrell } 1001673e404SJohn Birrell 1014cc75139SJohn Birrell static ctf_buf_t * 1021673e404SJohn Birrell ctf_buf_new(void) 1031673e404SJohn Birrell { 1041673e404SJohn Birrell ctf_buf_t *b = xcalloc(sizeof (ctf_buf_t)); 1051673e404SJohn Birrell 1061673e404SJohn Birrell strtab_create(&b->ctb_strtab); 1071673e404SJohn Birrell ctf_buf_grow(b); 1081673e404SJohn Birrell 1091673e404SJohn Birrell return (b); 1101673e404SJohn Birrell } 1111673e404SJohn Birrell 1124cc75139SJohn Birrell static void 1131673e404SJohn Birrell ctf_buf_free(ctf_buf_t *b) 1141673e404SJohn Birrell { 1151673e404SJohn Birrell strtab_destroy(&b->ctb_strtab); 1161673e404SJohn Birrell free(b->ctb_base); 1171673e404SJohn Birrell free(b); 1181673e404SJohn Birrell } 1191673e404SJohn Birrell 1204cc75139SJohn Birrell static uint_t 1211673e404SJohn Birrell ctf_buf_cur(ctf_buf_t *b) 1221673e404SJohn Birrell { 1231673e404SJohn Birrell return (b->ctb_ptr - b->ctb_base); 1241673e404SJohn Birrell } 1251673e404SJohn Birrell 1264cc75139SJohn Birrell static void 1274cc75139SJohn Birrell ctf_buf_write(ctf_buf_t *b, void const *p, size_t n) 1281673e404SJohn Birrell { 1291673e404SJohn Birrell size_t len; 1301673e404SJohn Birrell 1311673e404SJohn Birrell while (n != 0) { 1321673e404SJohn Birrell if (b->ctb_ptr == b->ctb_end) 1331673e404SJohn Birrell ctf_buf_grow(b); 1341673e404SJohn Birrell 1351673e404SJohn Birrell len = MIN((size_t)(b->ctb_end - b->ctb_ptr), n); 1361673e404SJohn Birrell bcopy(p, b->ctb_ptr, len); 1371673e404SJohn Birrell b->ctb_ptr += len; 1381673e404SJohn Birrell 1394cc75139SJohn Birrell p = (char const *)p + len; 1401673e404SJohn Birrell n -= len; 1411673e404SJohn Birrell } 1421673e404SJohn Birrell } 1431673e404SJohn Birrell 1441673e404SJohn Birrell static int 1454cc75139SJohn Birrell write_label(void *arg1, void *arg2) 1461673e404SJohn Birrell { 1474cc75139SJohn Birrell labelent_t *le = arg1; 1484cc75139SJohn Birrell ctf_buf_t *b = arg2; 1491673e404SJohn Birrell ctf_lblent_t ctl; 1501673e404SJohn Birrell 1511673e404SJohn Birrell ctl.ctl_label = strtab_insert(&b->ctb_strtab, le->le_name); 1521673e404SJohn Birrell ctl.ctl_typeidx = le->le_idx; 1531673e404SJohn Birrell 154a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 155a6425ab5SOleksandr Tymoshenko SWAP_32(ctl.ctl_label); 156a6425ab5SOleksandr Tymoshenko SWAP_32(ctl.ctl_typeidx); 157a6425ab5SOleksandr Tymoshenko } 158a6425ab5SOleksandr Tymoshenko 1591673e404SJohn Birrell ctf_buf_write(b, &ctl, sizeof (ctl)); 1601673e404SJohn Birrell 1611673e404SJohn Birrell return (1); 1621673e404SJohn Birrell } 1631673e404SJohn Birrell 1641673e404SJohn Birrell static void 1651673e404SJohn Birrell write_objects(iidesc_t *idp, ctf_buf_t *b) 1661673e404SJohn Birrell { 167*bdf290cdSMark Johnston uint_t id = (idp ? idp->ii_dtype->t_id : 0); 1681673e404SJohn Birrell 169a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 170*bdf290cdSMark Johnston SWAP_32(id); 171a6425ab5SOleksandr Tymoshenko } 172a6425ab5SOleksandr Tymoshenko 173fcb56067SGeorge V. Neville-Neil ctf_buf_write(b, &id, sizeof (id)); 174fcb56067SGeorge V. Neville-Neil 1751673e404SJohn Birrell debug(3, "Wrote object %s (%d)\n", (idp ? idp->ii_name : "(null)"), id); 1761673e404SJohn Birrell } 1771673e404SJohn Birrell 1781673e404SJohn Birrell static void 1791673e404SJohn Birrell write_functions(iidesc_t *idp, ctf_buf_t *b) 1801673e404SJohn Birrell { 181*bdf290cdSMark Johnston uint_t fdata[2]; 182*bdf290cdSMark Johnston uint_t id; 1831673e404SJohn Birrell int nargs; 1841673e404SJohn Birrell int i; 1851673e404SJohn Birrell 1861673e404SJohn Birrell if (!idp) { 1871673e404SJohn Birrell fdata[0] = 0; 1881673e404SJohn Birrell ctf_buf_write(b, &fdata[0], sizeof (fdata[0])); 1891673e404SJohn Birrell 1901673e404SJohn Birrell debug(3, "Wrote function (null)\n"); 1911673e404SJohn Birrell return; 1921673e404SJohn Birrell } 1931673e404SJohn Birrell 1941673e404SJohn Birrell nargs = idp->ii_nargs + (idp->ii_vargs != 0); 1951670a1c2SRui Paulo 196*bdf290cdSMark Johnston if (nargs > CTF_V3_MAX_VLEN) { 1971670a1c2SRui Paulo terminate("function %s has too many args: %d > %d\n", 198*bdf290cdSMark Johnston idp->ii_name, nargs, CTF_V3_MAX_VLEN); 1991670a1c2SRui Paulo } 2001670a1c2SRui Paulo 201*bdf290cdSMark Johnston fdata[0] = CTF_V3_TYPE_INFO(CTF_K_FUNCTION, 1, nargs); 2021673e404SJohn Birrell fdata[1] = idp->ii_dtype->t_id; 203a6425ab5SOleksandr Tymoshenko 204a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 205*bdf290cdSMark Johnston SWAP_32(fdata[0]); 206*bdf290cdSMark Johnston SWAP_32(fdata[1]); 207a6425ab5SOleksandr Tymoshenko } 208a6425ab5SOleksandr Tymoshenko 2091673e404SJohn Birrell ctf_buf_write(b, fdata, sizeof (fdata)); 2101673e404SJohn Birrell 2111673e404SJohn Birrell for (i = 0; i < idp->ii_nargs; i++) { 2121673e404SJohn Birrell id = idp->ii_args[i]->t_id; 213a6425ab5SOleksandr Tymoshenko 214a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 215*bdf290cdSMark Johnston SWAP_32(id); 216a6425ab5SOleksandr Tymoshenko } 217a6425ab5SOleksandr Tymoshenko 2181673e404SJohn Birrell ctf_buf_write(b, &id, sizeof (id)); 2191673e404SJohn Birrell } 2201673e404SJohn Birrell 2211673e404SJohn Birrell if (idp->ii_vargs) { 2221673e404SJohn Birrell id = 0; 2231673e404SJohn Birrell ctf_buf_write(b, &id, sizeof (id)); 2241673e404SJohn Birrell } 2251673e404SJohn Birrell 2261673e404SJohn Birrell debug(3, "Wrote function %s (%d args)\n", idp->ii_name, nargs); 2271673e404SJohn Birrell } 2281673e404SJohn Birrell 2291673e404SJohn Birrell /* 2301673e404SJohn Birrell * Depending on the size of the type being described, either a ctf_stype_t (for 2311673e404SJohn Birrell * types with size < CTF_LSTRUCT_THRESH) or a ctf_type_t (all others) will be 2321673e404SJohn Birrell * written. We isolate the determination here so the rest of the writer code 2331673e404SJohn Birrell * doesn't need to care. 2341673e404SJohn Birrell */ 2351673e404SJohn Birrell static void 236*bdf290cdSMark Johnston write_sized_type_rec(ctf_buf_t *b, struct ctf_type_v3 *ctt, size_t size) 2371673e404SJohn Birrell { 238*bdf290cdSMark Johnston if (size > CTF_V3_MAX_SIZE) { 239*bdf290cdSMark Johnston ctt->ctt_size = CTF_V3_LSIZE_SENT; 2401673e404SJohn Birrell ctt->ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size); 2411673e404SJohn Birrell ctt->ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size); 242a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 243a6425ab5SOleksandr Tymoshenko SWAP_32(ctt->ctt_name); 244*bdf290cdSMark Johnston SWAP_32(ctt->ctt_info); 245*bdf290cdSMark Johnston SWAP_32(ctt->ctt_size); 246a6425ab5SOleksandr Tymoshenko SWAP_32(ctt->ctt_lsizehi); 247a6425ab5SOleksandr Tymoshenko SWAP_32(ctt->ctt_lsizelo); 248a6425ab5SOleksandr Tymoshenko } 2491673e404SJohn Birrell ctf_buf_write(b, ctt, sizeof (*ctt)); 2501673e404SJohn Birrell } else { 251*bdf290cdSMark Johnston struct ctf_stype_v3 *cts = (struct ctf_stype_v3 *)ctt; 2521673e404SJohn Birrell 253*bdf290cdSMark Johnston cts->ctt_size = size; 254a6425ab5SOleksandr Tymoshenko 255a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 256a6425ab5SOleksandr Tymoshenko SWAP_32(cts->ctt_name); 257*bdf290cdSMark Johnston SWAP_32(cts->ctt_info); 258*bdf290cdSMark Johnston SWAP_32(cts->ctt_size); 259a6425ab5SOleksandr Tymoshenko } 260a6425ab5SOleksandr Tymoshenko 2611673e404SJohn Birrell ctf_buf_write(b, cts, sizeof (*cts)); 2621673e404SJohn Birrell } 2631673e404SJohn Birrell } 2641673e404SJohn Birrell 2651673e404SJohn Birrell static void 266*bdf290cdSMark Johnston write_unsized_type_rec(ctf_buf_t *b, struct ctf_type_v3 *ctt) 2671673e404SJohn Birrell { 268*bdf290cdSMark Johnston struct ctf_stype_v3 *cts = (struct ctf_stype_v3 *)ctt; 2691673e404SJohn Birrell 270a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 271a6425ab5SOleksandr Tymoshenko SWAP_32(cts->ctt_name); 272*bdf290cdSMark Johnston SWAP_32(cts->ctt_info); 273*bdf290cdSMark Johnston SWAP_32(cts->ctt_size); 274a6425ab5SOleksandr Tymoshenko } 275a6425ab5SOleksandr Tymoshenko 2761673e404SJohn Birrell ctf_buf_write(b, cts, sizeof (*cts)); 2771673e404SJohn Birrell } 2781673e404SJohn Birrell 2791673e404SJohn Birrell static int 2804cc75139SJohn Birrell write_type(void *arg1, void *arg2) 2811673e404SJohn Birrell { 2824cc75139SJohn Birrell tdesc_t *tp = arg1; 2834cc75139SJohn Birrell ctf_buf_t *b = arg2; 2841673e404SJohn Birrell elist_t *ep; 2851673e404SJohn Birrell mlist_t *mp; 2861673e404SJohn Birrell intr_t *ip; 2871673e404SJohn Birrell 2881673e404SJohn Birrell size_t offset; 2891673e404SJohn Birrell uint_t encoding; 2901673e404SJohn Birrell uint_t data; 2911673e404SJohn Birrell int isroot = tp->t_flags & TDESC_F_ISROOT; 2921673e404SJohn Birrell int i; 2931673e404SJohn Birrell 294*bdf290cdSMark Johnston struct ctf_type_v3 ctt; 295*bdf290cdSMark Johnston struct ctf_array_v3 cta; 296*bdf290cdSMark Johnston struct ctf_member_v3 ctm; 297*bdf290cdSMark Johnston struct ctf_lmember_v3 ctlm; 298*bdf290cdSMark Johnston struct ctf_enum cte; 299*bdf290cdSMark Johnston uint_t id; 3001673e404SJohn Birrell 3011673e404SJohn Birrell /* 3021673e404SJohn Birrell * There shouldn't be any holes in the type list (where a hole is 3031673e404SJohn Birrell * defined as two consecutive tdescs without consecutive ids), but 3041673e404SJohn Birrell * check for them just in case. If we do find holes, we need to make 3051673e404SJohn Birrell * fake entries to fill the holes, or we won't be able to reconstruct 3061673e404SJohn Birrell * the tree from the written data. 3071673e404SJohn Birrell */ 308*bdf290cdSMark Johnston if (++b->nptent < CTF_V3_TYPE_TO_INDEX(tp->t_id)) { 3091673e404SJohn Birrell debug(2, "genctf: type hole from %d < x < %d\n", 310*bdf290cdSMark Johnston b->nptent - 1, CTF_V3_TYPE_TO_INDEX(tp->t_id)); 3111673e404SJohn Birrell 3121673e404SJohn Birrell ctt.ctt_name = CTF_TYPE_NAME(CTF_STRTAB_0, 0); 313*bdf290cdSMark Johnston ctt.ctt_info = CTF_V3_TYPE_INFO(0, 0, 0); 314*bdf290cdSMark Johnston while (b->nptent < CTF_V3_TYPE_TO_INDEX(tp->t_id)) { 3151673e404SJohn Birrell write_sized_type_rec(b, &ctt, 0); 3161673e404SJohn Birrell b->nptent++; 3171673e404SJohn Birrell } 3181673e404SJohn Birrell } 3191673e404SJohn Birrell 3201673e404SJohn Birrell offset = strtab_insert(&b->ctb_strtab, tp->t_name); 3211673e404SJohn Birrell ctt.ctt_name = CTF_TYPE_NAME(CTF_STRTAB_0, offset); 3221673e404SJohn Birrell 3231673e404SJohn Birrell switch (tp->t_type) { 3241673e404SJohn Birrell case INTRINSIC: 3251673e404SJohn Birrell ip = tp->t_intr; 3261673e404SJohn Birrell if (ip->intr_type == INTR_INT) 327*bdf290cdSMark Johnston ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_INTEGER, 3281673e404SJohn Birrell isroot, 1); 3291673e404SJohn Birrell else 330*bdf290cdSMark Johnston ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_FLOAT, isroot, 1); 3311673e404SJohn Birrell write_sized_type_rec(b, &ctt, tp->t_size); 3321673e404SJohn Birrell 3331673e404SJohn Birrell encoding = 0; 3341673e404SJohn Birrell 3351673e404SJohn Birrell if (ip->intr_type == INTR_INT) { 3361673e404SJohn Birrell if (ip->intr_signed) 3371673e404SJohn Birrell encoding |= CTF_INT_SIGNED; 3381673e404SJohn Birrell if (ip->intr_iformat == 'c') 3391673e404SJohn Birrell encoding |= CTF_INT_CHAR; 3401673e404SJohn Birrell else if (ip->intr_iformat == 'b') 3411673e404SJohn Birrell encoding |= CTF_INT_BOOL; 3421673e404SJohn Birrell else if (ip->intr_iformat == 'v') 3431673e404SJohn Birrell encoding |= CTF_INT_VARARGS; 3441673e404SJohn Birrell } else 3451673e404SJohn Birrell encoding = ip->intr_fformat; 3461673e404SJohn Birrell 3471673e404SJohn Birrell data = CTF_INT_DATA(encoding, ip->intr_offset, ip->intr_nbits); 348a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 349a6425ab5SOleksandr Tymoshenko SWAP_32(data); 350a6425ab5SOleksandr Tymoshenko } 3511673e404SJohn Birrell ctf_buf_write(b, &data, sizeof (data)); 3521673e404SJohn Birrell break; 3531673e404SJohn Birrell 3541673e404SJohn Birrell case POINTER: 355*bdf290cdSMark Johnston ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_POINTER, isroot, 0); 3561673e404SJohn Birrell ctt.ctt_type = tp->t_tdesc->t_id; 3571673e404SJohn Birrell write_unsized_type_rec(b, &ctt); 3581673e404SJohn Birrell break; 3591673e404SJohn Birrell 3601673e404SJohn Birrell case ARRAY: 361*bdf290cdSMark Johnston ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_ARRAY, isroot, 1); 3621673e404SJohn Birrell write_sized_type_rec(b, &ctt, tp->t_size); 3631673e404SJohn Birrell 3641673e404SJohn Birrell cta.cta_contents = tp->t_ardef->ad_contents->t_id; 3651673e404SJohn Birrell cta.cta_index = tp->t_ardef->ad_idxtype->t_id; 3661673e404SJohn Birrell cta.cta_nelems = tp->t_ardef->ad_nelems; 367a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 368*bdf290cdSMark Johnston SWAP_32(cta.cta_contents); 369*bdf290cdSMark Johnston SWAP_32(cta.cta_index); 370a6425ab5SOleksandr Tymoshenko SWAP_32(cta.cta_nelems); 371a6425ab5SOleksandr Tymoshenko } 3721673e404SJohn Birrell ctf_buf_write(b, &cta, sizeof (cta)); 3731673e404SJohn Birrell break; 3741673e404SJohn Birrell 3751673e404SJohn Birrell case STRUCT: 3761673e404SJohn Birrell case UNION: 3771673e404SJohn Birrell for (i = 0, mp = tp->t_members; mp != NULL; mp = mp->ml_next) 3781673e404SJohn Birrell i++; /* count up struct or union members */ 3791673e404SJohn Birrell 380*bdf290cdSMark Johnston if (i > CTF_V3_MAX_VLEN) { 3811670a1c2SRui Paulo terminate("sou %s has too many members: %d > %d\n", 382*bdf290cdSMark Johnston tdesc_name(tp), i, CTF_V3_MAX_VLEN); 3831670a1c2SRui Paulo } 3841670a1c2SRui Paulo 3851673e404SJohn Birrell if (tp->t_type == STRUCT) 386*bdf290cdSMark Johnston ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_STRUCT, isroot, i); 3871673e404SJohn Birrell else 388*bdf290cdSMark Johnston ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_UNION, isroot, i); 3891673e404SJohn Birrell 3901673e404SJohn Birrell write_sized_type_rec(b, &ctt, tp->t_size); 3911673e404SJohn Birrell 392*bdf290cdSMark Johnston if (tp->t_size < CTF_V3_LSTRUCT_THRESH) { 3931673e404SJohn Birrell for (mp = tp->t_members; mp != NULL; mp = mp->ml_next) { 3941673e404SJohn Birrell offset = strtab_insert(&b->ctb_strtab, 3951673e404SJohn Birrell mp->ml_name); 3961673e404SJohn Birrell 3971673e404SJohn Birrell ctm.ctm_name = CTF_TYPE_NAME(CTF_STRTAB_0, 3981673e404SJohn Birrell offset); 3991673e404SJohn Birrell ctm.ctm_type = mp->ml_type->t_id; 4001673e404SJohn Birrell ctm.ctm_offset = mp->ml_offset; 401a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 402a6425ab5SOleksandr Tymoshenko SWAP_32(ctm.ctm_name); 403*bdf290cdSMark Johnston SWAP_32(ctm.ctm_type); 404*bdf290cdSMark Johnston SWAP_32(ctm.ctm_offset); 405a6425ab5SOleksandr Tymoshenko } 4061673e404SJohn Birrell ctf_buf_write(b, &ctm, sizeof (ctm)); 4071673e404SJohn Birrell } 4081673e404SJohn Birrell } else { 4091673e404SJohn Birrell for (mp = tp->t_members; mp != NULL; mp = mp->ml_next) { 4101673e404SJohn Birrell offset = strtab_insert(&b->ctb_strtab, 4111673e404SJohn Birrell mp->ml_name); 4121673e404SJohn Birrell 4131673e404SJohn Birrell ctlm.ctlm_name = CTF_TYPE_NAME(CTF_STRTAB_0, 4141673e404SJohn Birrell offset); 4151673e404SJohn Birrell ctlm.ctlm_type = mp->ml_type->t_id; 4161673e404SJohn Birrell ctlm.ctlm_offsethi = 4171673e404SJohn Birrell CTF_OFFSET_TO_LMEMHI(mp->ml_offset); 4181673e404SJohn Birrell ctlm.ctlm_offsetlo = 4191673e404SJohn Birrell CTF_OFFSET_TO_LMEMLO(mp->ml_offset); 420a6425ab5SOleksandr Tymoshenko 421a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 422a6425ab5SOleksandr Tymoshenko SWAP_32(ctlm.ctlm_name); 423*bdf290cdSMark Johnston SWAP_32(ctlm.ctlm_type); 424a6425ab5SOleksandr Tymoshenko SWAP_32(ctlm.ctlm_offsethi); 425a6425ab5SOleksandr Tymoshenko SWAP_32(ctlm.ctlm_offsetlo); 426a6425ab5SOleksandr Tymoshenko } 427a6425ab5SOleksandr Tymoshenko 4281673e404SJohn Birrell ctf_buf_write(b, &ctlm, sizeof (ctlm)); 4291673e404SJohn Birrell } 4301673e404SJohn Birrell } 4311673e404SJohn Birrell break; 4321673e404SJohn Birrell 4331673e404SJohn Birrell case ENUM: 4341673e404SJohn Birrell for (i = 0, ep = tp->t_emem; ep != NULL; ep = ep->el_next) 4351673e404SJohn Birrell i++; /* count up enum members */ 4361673e404SJohn Birrell 437*bdf290cdSMark Johnston if (i > CTF_V3_MAX_VLEN) { 438*bdf290cdSMark Johnston i = CTF_V3_MAX_VLEN; 43959879e52SAlexander Kabaev } 44059879e52SAlexander Kabaev 441*bdf290cdSMark Johnston ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_ENUM, isroot, i); 4421673e404SJohn Birrell write_sized_type_rec(b, &ctt, tp->t_size); 4431673e404SJohn Birrell 44459879e52SAlexander Kabaev for (ep = tp->t_emem; ep != NULL && i > 0; ep = ep->el_next) { 4451673e404SJohn Birrell offset = strtab_insert(&b->ctb_strtab, ep->el_name); 4461673e404SJohn Birrell cte.cte_name = CTF_TYPE_NAME(CTF_STRTAB_0, offset); 4471673e404SJohn Birrell cte.cte_value = ep->el_number; 448a6425ab5SOleksandr Tymoshenko 449a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 450a6425ab5SOleksandr Tymoshenko SWAP_32(cte.cte_name); 451a6425ab5SOleksandr Tymoshenko SWAP_32(cte.cte_value); 452a6425ab5SOleksandr Tymoshenko } 453a6425ab5SOleksandr Tymoshenko 4541673e404SJohn Birrell ctf_buf_write(b, &cte, sizeof (cte)); 45559879e52SAlexander Kabaev i--; 4561673e404SJohn Birrell } 4571673e404SJohn Birrell break; 4581673e404SJohn Birrell 4591673e404SJohn Birrell case FORWARD: 460*bdf290cdSMark Johnston ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_FORWARD, isroot, 0); 4611673e404SJohn Birrell ctt.ctt_type = 0; 4621673e404SJohn Birrell write_unsized_type_rec(b, &ctt); 4631673e404SJohn Birrell break; 4641673e404SJohn Birrell 4651673e404SJohn Birrell case TYPEDEF: 466*bdf290cdSMark Johnston ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_TYPEDEF, isroot, 0); 4671673e404SJohn Birrell ctt.ctt_type = tp->t_tdesc->t_id; 4681673e404SJohn Birrell write_unsized_type_rec(b, &ctt); 4691673e404SJohn Birrell break; 4701673e404SJohn Birrell 4711673e404SJohn Birrell case VOLATILE: 472*bdf290cdSMark Johnston ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_VOLATILE, isroot, 0); 4731673e404SJohn Birrell ctt.ctt_type = tp->t_tdesc->t_id; 4741673e404SJohn Birrell write_unsized_type_rec(b, &ctt); 4751673e404SJohn Birrell break; 4761673e404SJohn Birrell 4771673e404SJohn Birrell case CONST: 478*bdf290cdSMark Johnston ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_CONST, isroot, 0); 4791673e404SJohn Birrell ctt.ctt_type = tp->t_tdesc->t_id; 4801673e404SJohn Birrell write_unsized_type_rec(b, &ctt); 4811673e404SJohn Birrell break; 4821673e404SJohn Birrell 4831673e404SJohn Birrell case FUNCTION: 4841670a1c2SRui Paulo i = tp->t_fndef->fn_nargs + tp->t_fndef->fn_vargs; 4851670a1c2SRui Paulo 486*bdf290cdSMark Johnston if (i > CTF_V3_MAX_VLEN) { 4871670a1c2SRui Paulo terminate("function %s has too many args: %d > %d\n", 488*bdf290cdSMark Johnston tdesc_name(tp), i, CTF_V3_MAX_VLEN); 4891670a1c2SRui Paulo } 4901670a1c2SRui Paulo 491*bdf290cdSMark Johnston ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_FUNCTION, isroot, i); 4921673e404SJohn Birrell ctt.ctt_type = tp->t_fndef->fn_ret->t_id; 4931673e404SJohn Birrell write_unsized_type_rec(b, &ctt); 4941673e404SJohn Birrell 4954cc75139SJohn Birrell for (i = 0; i < (int) tp->t_fndef->fn_nargs; i++) { 4961673e404SJohn Birrell id = tp->t_fndef->fn_args[i]->t_id; 497a6425ab5SOleksandr Tymoshenko 498a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 499*bdf290cdSMark Johnston SWAP_32(id); 500a6425ab5SOleksandr Tymoshenko } 501a6425ab5SOleksandr Tymoshenko 5021673e404SJohn Birrell ctf_buf_write(b, &id, sizeof (id)); 5031673e404SJohn Birrell } 5041673e404SJohn Birrell 5051673e404SJohn Birrell if (tp->t_fndef->fn_vargs) { 5061673e404SJohn Birrell id = 0; 5071673e404SJohn Birrell ctf_buf_write(b, &id, sizeof (id)); 5081673e404SJohn Birrell i++; 5091673e404SJohn Birrell } 5101673e404SJohn Birrell 5111673e404SJohn Birrell break; 5121673e404SJohn Birrell 5131673e404SJohn Birrell case RESTRICT: 514*bdf290cdSMark Johnston ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_RESTRICT, isroot, 0); 5151673e404SJohn Birrell ctt.ctt_type = tp->t_tdesc->t_id; 5161673e404SJohn Birrell write_unsized_type_rec(b, &ctt); 5171673e404SJohn Birrell break; 5181673e404SJohn Birrell 5191673e404SJohn Birrell default: 5201673e404SJohn Birrell warning("Can't write unknown type %d\n", tp->t_type); 5211673e404SJohn Birrell } 5221673e404SJohn Birrell 5231673e404SJohn Birrell debug(3, "Wrote type %d %s\n", tp->t_id, tdesc_name(tp)); 5241673e404SJohn Birrell 5251673e404SJohn Birrell return (1); 5261673e404SJohn Birrell } 5271673e404SJohn Birrell 5281673e404SJohn Birrell typedef struct resbuf { 5291673e404SJohn Birrell caddr_t rb_base; 5301673e404SJohn Birrell caddr_t rb_ptr; 5311673e404SJohn Birrell size_t rb_size; 5321673e404SJohn Birrell z_stream rb_zstr; 5331673e404SJohn Birrell } resbuf_t; 5341673e404SJohn Birrell 5351673e404SJohn Birrell static void 5361673e404SJohn Birrell rbzs_grow(resbuf_t *rb) 5371673e404SJohn Birrell { 5381673e404SJohn Birrell off_t ptroff = (caddr_t)rb->rb_zstr.next_out - rb->rb_base; 5391673e404SJohn Birrell 5401673e404SJohn Birrell rb->rb_size += RES_BUF_CHUNK_SIZE; 5411673e404SJohn Birrell rb->rb_base = xrealloc(rb->rb_base, rb->rb_size); 5421673e404SJohn Birrell rb->rb_ptr = rb->rb_base + ptroff; 5431673e404SJohn Birrell rb->rb_zstr.next_out = (Bytef *)(rb->rb_ptr); 5441673e404SJohn Birrell rb->rb_zstr.avail_out += RES_BUF_CHUNK_SIZE; 5451673e404SJohn Birrell } 5461673e404SJohn Birrell 5471673e404SJohn Birrell static void 5481673e404SJohn Birrell compress_start(resbuf_t *rb) 5491673e404SJohn Birrell { 5501673e404SJohn Birrell int rc; 5511673e404SJohn Birrell 5521673e404SJohn Birrell rb->rb_zstr.zalloc = (alloc_func)0; 5531673e404SJohn Birrell rb->rb_zstr.zfree = (free_func)0; 5541673e404SJohn Birrell rb->rb_zstr.opaque = (voidpf)0; 5551673e404SJohn Birrell 5561673e404SJohn Birrell if ((rc = deflateInit(&rb->rb_zstr, Z_BEST_COMPRESSION)) != Z_OK) 5571673e404SJohn Birrell parseterminate("zlib start failed: %s", zError(rc)); 5581673e404SJohn Birrell } 5591673e404SJohn Birrell 5601673e404SJohn Birrell static ssize_t 5614cc75139SJohn Birrell compress_buffer(void *buf, size_t n, void *data) 5621673e404SJohn Birrell { 5631673e404SJohn Birrell resbuf_t *rb = (resbuf_t *)data; 5641673e404SJohn Birrell int rc; 5651673e404SJohn Birrell 5661673e404SJohn Birrell rb->rb_zstr.next_out = (Bytef *)rb->rb_ptr; 5671673e404SJohn Birrell rb->rb_zstr.avail_out = rb->rb_size - (rb->rb_ptr - rb->rb_base); 5684cc75139SJohn Birrell rb->rb_zstr.next_in = buf; 5691673e404SJohn Birrell rb->rb_zstr.avail_in = n; 5701673e404SJohn Birrell 5711673e404SJohn Birrell while (rb->rb_zstr.avail_in) { 5721673e404SJohn Birrell if (rb->rb_zstr.avail_out == 0) 5731673e404SJohn Birrell rbzs_grow(rb); 5741673e404SJohn Birrell 5751673e404SJohn Birrell if ((rc = deflate(&rb->rb_zstr, Z_NO_FLUSH)) != Z_OK) 5761673e404SJohn Birrell parseterminate("zlib deflate failed: %s", zError(rc)); 5771673e404SJohn Birrell } 5781673e404SJohn Birrell rb->rb_ptr = (caddr_t)rb->rb_zstr.next_out; 5791673e404SJohn Birrell 5801673e404SJohn Birrell return (n); 5811673e404SJohn Birrell } 5821673e404SJohn Birrell 5831673e404SJohn Birrell static void 5841673e404SJohn Birrell compress_flush(resbuf_t *rb, int type) 5851673e404SJohn Birrell { 5861673e404SJohn Birrell int rc; 5871673e404SJohn Birrell 5881673e404SJohn Birrell for (;;) { 5891673e404SJohn Birrell if (rb->rb_zstr.avail_out == 0) 5901673e404SJohn Birrell rbzs_grow(rb); 5911673e404SJohn Birrell 5921673e404SJohn Birrell rc = deflate(&rb->rb_zstr, type); 5931673e404SJohn Birrell if ((type == Z_FULL_FLUSH && rc == Z_BUF_ERROR) || 5941673e404SJohn Birrell (type == Z_FINISH && rc == Z_STREAM_END)) 5951673e404SJohn Birrell break; 5961673e404SJohn Birrell else if (rc != Z_OK) 5971673e404SJohn Birrell parseterminate("zlib finish failed: %s", zError(rc)); 5981673e404SJohn Birrell } 5991673e404SJohn Birrell rb->rb_ptr = (caddr_t)rb->rb_zstr.next_out; 6001673e404SJohn Birrell } 6011673e404SJohn Birrell 6021673e404SJohn Birrell static void 6031673e404SJohn Birrell compress_end(resbuf_t *rb) 6041673e404SJohn Birrell { 6051673e404SJohn Birrell int rc; 6061673e404SJohn Birrell 6071673e404SJohn Birrell compress_flush(rb, Z_FINISH); 6081673e404SJohn Birrell 6091673e404SJohn Birrell if ((rc = deflateEnd(&rb->rb_zstr)) != Z_OK) 6101673e404SJohn Birrell parseterminate("zlib end failed: %s", zError(rc)); 6111673e404SJohn Birrell } 6121673e404SJohn Birrell 6131673e404SJohn Birrell /* 6141673e404SJohn Birrell * Pad the buffer to a power-of-2 boundary 6151673e404SJohn Birrell */ 6161673e404SJohn Birrell static void 6171673e404SJohn Birrell pad_buffer(ctf_buf_t *buf, int align) 6181673e404SJohn Birrell { 6191673e404SJohn Birrell uint_t cur = ctf_buf_cur(buf); 6201673e404SJohn Birrell ssize_t topad = (align - (cur % align)) % align; 6211673e404SJohn Birrell static const char pad[8] = { 0 }; 6221673e404SJohn Birrell 6231673e404SJohn Birrell while (topad > 0) { 6241673e404SJohn Birrell ctf_buf_write(buf, pad, (topad > 8 ? 8 : topad)); 6251673e404SJohn Birrell topad -= 8; 6261673e404SJohn Birrell } 6271673e404SJohn Birrell } 6281673e404SJohn Birrell 6291673e404SJohn Birrell static ssize_t 6304cc75139SJohn Birrell bcopy_data(void *buf, size_t n, void *data) 6311673e404SJohn Birrell { 6321673e404SJohn Birrell caddr_t *posp = (caddr_t *)data; 6331673e404SJohn Birrell bcopy(buf, *posp, n); 6341673e404SJohn Birrell *posp += n; 6351673e404SJohn Birrell return (n); 6361673e404SJohn Birrell } 6371673e404SJohn Birrell 6381673e404SJohn Birrell static caddr_t 6391673e404SJohn Birrell write_buffer(ctf_header_t *h, ctf_buf_t *buf, size_t *resszp) 6401673e404SJohn Birrell { 6411673e404SJohn Birrell caddr_t outbuf; 6421673e404SJohn Birrell caddr_t bufpos; 6431673e404SJohn Birrell 6441673e404SJohn Birrell outbuf = xmalloc(sizeof (ctf_header_t) + (buf->ctb_ptr - buf->ctb_base) 6451673e404SJohn Birrell + buf->ctb_strtab.str_size); 6461673e404SJohn Birrell 6471673e404SJohn Birrell bufpos = outbuf; 6481673e404SJohn Birrell (void) bcopy_data(h, sizeof (ctf_header_t), &bufpos); 6491673e404SJohn Birrell (void) bcopy_data(buf->ctb_base, buf->ctb_ptr - buf->ctb_base, 6501673e404SJohn Birrell &bufpos); 6511673e404SJohn Birrell (void) strtab_write(&buf->ctb_strtab, bcopy_data, &bufpos); 6521673e404SJohn Birrell *resszp = bufpos - outbuf; 6531673e404SJohn Birrell return (outbuf); 6541673e404SJohn Birrell } 6551673e404SJohn Birrell 6561673e404SJohn Birrell /* 6571673e404SJohn Birrell * Create the compression buffer, and fill it with the CTF and string 6581673e404SJohn Birrell * table data. We flush the compression state between the two so the 6591673e404SJohn Birrell * dictionary used for the string tables won't be polluted with values 6601673e404SJohn Birrell * that made sense for the CTF data. 6611673e404SJohn Birrell */ 6621673e404SJohn Birrell static caddr_t 6631673e404SJohn Birrell write_compressed_buffer(ctf_header_t *h, ctf_buf_t *buf, size_t *resszp) 6641673e404SJohn Birrell { 6651673e404SJohn Birrell resbuf_t resbuf; 6661673e404SJohn Birrell resbuf.rb_size = RES_BUF_CHUNK_SIZE; 6671673e404SJohn Birrell resbuf.rb_base = xmalloc(resbuf.rb_size); 6681673e404SJohn Birrell bcopy(h, resbuf.rb_base, sizeof (ctf_header_t)); 6691673e404SJohn Birrell resbuf.rb_ptr = resbuf.rb_base + sizeof (ctf_header_t); 6701673e404SJohn Birrell 6711673e404SJohn Birrell compress_start(&resbuf); 6721673e404SJohn Birrell (void) compress_buffer(buf->ctb_base, buf->ctb_ptr - buf->ctb_base, 6731673e404SJohn Birrell &resbuf); 6741673e404SJohn Birrell compress_flush(&resbuf, Z_FULL_FLUSH); 6751673e404SJohn Birrell (void) strtab_write(&buf->ctb_strtab, compress_buffer, &resbuf); 6761673e404SJohn Birrell compress_end(&resbuf); 6771673e404SJohn Birrell 6781673e404SJohn Birrell *resszp = (resbuf.rb_ptr - resbuf.rb_base); 6791673e404SJohn Birrell return (resbuf.rb_base); 6801673e404SJohn Birrell } 6811673e404SJohn Birrell 6821673e404SJohn Birrell caddr_t 6831673e404SJohn Birrell ctf_gen(iiburst_t *iiburst, size_t *resszp, int do_compress) 6841673e404SJohn Birrell { 6851673e404SJohn Birrell ctf_buf_t *buf = ctf_buf_new(); 6861673e404SJohn Birrell ctf_header_t h; 6871673e404SJohn Birrell caddr_t outbuf; 6881673e404SJohn Birrell 6891673e404SJohn Birrell int i; 6901673e404SJohn Birrell 691a6425ab5SOleksandr Tymoshenko target_requires_swap = do_compress & CTF_SWAP_BYTES; 692a6425ab5SOleksandr Tymoshenko do_compress &= ~CTF_SWAP_BYTES; 693a6425ab5SOleksandr Tymoshenko 6941673e404SJohn Birrell /* 6951673e404SJohn Birrell * Prepare the header, and create the CTF output buffers. The data 6961673e404SJohn Birrell * object section and function section are both lists of 2-byte 6971673e404SJohn Birrell * integers; we pad these out to the next 4-byte boundary if needed. 6981673e404SJohn Birrell */ 6991673e404SJohn Birrell h.cth_magic = CTF_MAGIC; 700*bdf290cdSMark Johnston h.cth_version = CTF_VERSION_3; 7011673e404SJohn Birrell h.cth_flags = do_compress ? CTF_F_COMPRESS : 0; 7021673e404SJohn Birrell h.cth_parlabel = strtab_insert(&buf->ctb_strtab, 7031673e404SJohn Birrell iiburst->iib_td->td_parlabel); 7041673e404SJohn Birrell h.cth_parname = strtab_insert(&buf->ctb_strtab, 7051673e404SJohn Birrell iiburst->iib_td->td_parname); 7061673e404SJohn Birrell 7071673e404SJohn Birrell h.cth_lbloff = 0; 7084cc75139SJohn Birrell (void) list_iter(iiburst->iib_td->td_labels, write_label, 7091673e404SJohn Birrell buf); 7101673e404SJohn Birrell 7111673e404SJohn Birrell pad_buffer(buf, 2); 7121673e404SJohn Birrell h.cth_objtoff = ctf_buf_cur(buf); 7131673e404SJohn Birrell for (i = 0; i < iiburst->iib_nobjts; i++) 7141673e404SJohn Birrell write_objects(iiburst->iib_objts[i], buf); 7151673e404SJohn Birrell 7161673e404SJohn Birrell pad_buffer(buf, 2); 7171673e404SJohn Birrell h.cth_funcoff = ctf_buf_cur(buf); 7181673e404SJohn Birrell for (i = 0; i < iiburst->iib_nfuncs; i++) 7191673e404SJohn Birrell write_functions(iiburst->iib_funcs[i], buf); 7201673e404SJohn Birrell 7211673e404SJohn Birrell pad_buffer(buf, 4); 7221673e404SJohn Birrell h.cth_typeoff = ctf_buf_cur(buf); 7234cc75139SJohn Birrell (void) list_iter(iiburst->iib_types, write_type, buf); 7241673e404SJohn Birrell 7251673e404SJohn Birrell debug(2, "CTF wrote %d types\n", list_count(iiburst->iib_types)); 7261673e404SJohn Birrell 7271673e404SJohn Birrell h.cth_stroff = ctf_buf_cur(buf); 7281673e404SJohn Birrell h.cth_strlen = strtab_size(&buf->ctb_strtab); 7291673e404SJohn Birrell 730a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 731a6425ab5SOleksandr Tymoshenko SWAP_16(h.cth_preamble.ctp_magic); 732a6425ab5SOleksandr Tymoshenko SWAP_32(h.cth_parlabel); 733a6425ab5SOleksandr Tymoshenko SWAP_32(h.cth_parname); 734a6425ab5SOleksandr Tymoshenko SWAP_32(h.cth_lbloff); 735a6425ab5SOleksandr Tymoshenko SWAP_32(h.cth_objtoff); 736a6425ab5SOleksandr Tymoshenko SWAP_32(h.cth_funcoff); 737a6425ab5SOleksandr Tymoshenko SWAP_32(h.cth_typeoff); 738a6425ab5SOleksandr Tymoshenko SWAP_32(h.cth_stroff); 739a6425ab5SOleksandr Tymoshenko SWAP_32(h.cth_strlen); 740a6425ab5SOleksandr Tymoshenko } 741a6425ab5SOleksandr Tymoshenko 7421673e404SJohn Birrell /* 7431673e404SJohn Birrell * We only do compression for ctfmerge, as ctfconvert is only 7441673e404SJohn Birrell * supposed to be used on intermediary build objects. This is 7451673e404SJohn Birrell * significantly faster. 7461673e404SJohn Birrell */ 7471673e404SJohn Birrell if (do_compress) 7481673e404SJohn Birrell outbuf = write_compressed_buffer(&h, buf, resszp); 7491673e404SJohn Birrell else 7501673e404SJohn Birrell outbuf = write_buffer(&h, buf, resszp); 7511673e404SJohn Birrell 7521673e404SJohn Birrell ctf_buf_free(buf); 7531673e404SJohn Birrell return (outbuf); 7541673e404SJohn Birrell } 7551673e404SJohn Birrell 7564cc75139SJohn Birrell static void 757*bdf290cdSMark Johnston get_ctt_info(ctf_header_t *h, void *v, uint_t *kind, uint_t *vlen, int *isroot) 7581673e404SJohn Birrell { 759*bdf290cdSMark Johnston if (h->cth_version == CTF_VERSION_2) { 760*bdf290cdSMark Johnston struct ctf_type_v2 *ctt = v; 761*bdf290cdSMark Johnston 762*bdf290cdSMark Johnston *kind = CTF_V2_INFO_KIND(ctt->ctt_info); 763*bdf290cdSMark Johnston *vlen = CTF_V2_INFO_VLEN(ctt->ctt_info); 764*bdf290cdSMark Johnston *isroot = CTF_V2_INFO_ISROOT(ctt->ctt_info); 765*bdf290cdSMark Johnston } else { 766*bdf290cdSMark Johnston struct ctf_type_v3 *ctt = v; 767*bdf290cdSMark Johnston 768*bdf290cdSMark Johnston *kind = CTF_V3_INFO_KIND(ctt->ctt_info); 769*bdf290cdSMark Johnston *vlen = CTF_V3_INFO_VLEN(ctt->ctt_info); 770*bdf290cdSMark Johnston *isroot = CTF_V3_INFO_ISROOT(ctt->ctt_info); 771*bdf290cdSMark Johnston } 772*bdf290cdSMark Johnston } 773*bdf290cdSMark Johnston 774*bdf290cdSMark Johnston static void 775*bdf290cdSMark Johnston get_ctt_size(ctf_header_t *h, void *v, size_t *sizep, size_t *incrementp) 776*bdf290cdSMark Johnston { 777*bdf290cdSMark Johnston if (h->cth_version == CTF_VERSION_2) { 778*bdf290cdSMark Johnston struct ctf_type_v2 *ctt = v; 779*bdf290cdSMark Johnston 780*bdf290cdSMark Johnston if (ctt->ctt_size == CTF_V2_LSIZE_SENT) { 7811673e404SJohn Birrell *sizep = (size_t)CTF_TYPE_LSIZE(ctt); 782*bdf290cdSMark Johnston *incrementp = sizeof (struct ctf_type_v2); 7831673e404SJohn Birrell } else { 7841673e404SJohn Birrell *sizep = ctt->ctt_size; 785*bdf290cdSMark Johnston *incrementp = sizeof (struct ctf_stype_v2); 786*bdf290cdSMark Johnston } 787*bdf290cdSMark Johnston } else { 788*bdf290cdSMark Johnston struct ctf_type_v3 *ctt = v; 789*bdf290cdSMark Johnston 790*bdf290cdSMark Johnston if (ctt->ctt_size == CTF_V3_LSIZE_SENT) { 791*bdf290cdSMark Johnston *sizep = (size_t)CTF_TYPE_LSIZE(ctt); 792*bdf290cdSMark Johnston *incrementp = sizeof (struct ctf_type_v3); 793*bdf290cdSMark Johnston } else { 794*bdf290cdSMark Johnston *sizep = ctt->ctt_size; 795*bdf290cdSMark Johnston *incrementp = sizeof (struct ctf_stype_v3); 796*bdf290cdSMark Johnston } 7971673e404SJohn Birrell } 7981673e404SJohn Birrell } 7991673e404SJohn Birrell 8001673e404SJohn Birrell static int 8011673e404SJohn Birrell count_types(ctf_header_t *h, caddr_t data) 8021673e404SJohn Birrell { 8031673e404SJohn Birrell caddr_t dptr = data + h->cth_typeoff; 804*bdf290cdSMark Johnston uint_t version = h->cth_version; 805*bdf290cdSMark Johnston size_t idwidth; 8061673e404SJohn Birrell int count = 0; 8071673e404SJohn Birrell 808*bdf290cdSMark Johnston idwidth = version == CTF_VERSION_2 ? 2 : 4; 8091673e404SJohn Birrell dptr = data + h->cth_typeoff; 8101673e404SJohn Birrell while (dptr < data + h->cth_stroff) { 8114cc75139SJohn Birrell void *v = (void *) dptr; 8121673e404SJohn Birrell size_t size, increment; 813*bdf290cdSMark Johnston uint_t vlen, kind; 814*bdf290cdSMark Johnston int isroot; 8151673e404SJohn Birrell 816*bdf290cdSMark Johnston get_ctt_info(h, v, &kind, &vlen, &isroot); 817*bdf290cdSMark Johnston get_ctt_size(h, v, &size, &increment); 8181673e404SJohn Birrell 819*bdf290cdSMark Johnston switch (kind) { 8201673e404SJohn Birrell case CTF_K_INTEGER: 8211673e404SJohn Birrell case CTF_K_FLOAT: 8221673e404SJohn Birrell dptr += 4; 8231673e404SJohn Birrell break; 8241673e404SJohn Birrell case CTF_K_POINTER: 8251673e404SJohn Birrell case CTF_K_FORWARD: 8261673e404SJohn Birrell case CTF_K_TYPEDEF: 8271673e404SJohn Birrell case CTF_K_VOLATILE: 8281673e404SJohn Birrell case CTF_K_CONST: 8291673e404SJohn Birrell case CTF_K_RESTRICT: 8301673e404SJohn Birrell case CTF_K_FUNCTION: 831*bdf290cdSMark Johnston dptr += idwidth * vlen; 8321673e404SJohn Birrell break; 8331673e404SJohn Birrell case CTF_K_ARRAY: 834*bdf290cdSMark Johnston if (version == CTF_VERSION_2) 835*bdf290cdSMark Johnston dptr += sizeof (struct ctf_array_v2); 836*bdf290cdSMark Johnston else 837*bdf290cdSMark Johnston dptr += sizeof (struct ctf_array_v3); 8381673e404SJohn Birrell break; 8391673e404SJohn Birrell case CTF_K_STRUCT: 8401673e404SJohn Birrell case CTF_K_UNION: 841*bdf290cdSMark Johnston if (version == CTF_VERSION_2) { 842*bdf290cdSMark Johnston if (size < CTF_V2_LSTRUCT_THRESH) 843*bdf290cdSMark Johnston dptr += sizeof (struct ctf_member_v2) * 844*bdf290cdSMark Johnston vlen; 8451673e404SJohn Birrell else 846*bdf290cdSMark Johnston dptr += sizeof (struct ctf_lmember_v2) * 847*bdf290cdSMark Johnston vlen; 848*bdf290cdSMark Johnston } else { 849*bdf290cdSMark Johnston if (size < CTF_V3_LSTRUCT_THRESH) 850*bdf290cdSMark Johnston dptr += sizeof (struct ctf_member_v3) * 851*bdf290cdSMark Johnston vlen; 852*bdf290cdSMark Johnston else 853*bdf290cdSMark Johnston dptr += sizeof (struct ctf_lmember_v3) * 854*bdf290cdSMark Johnston vlen; 855*bdf290cdSMark Johnston } 8561673e404SJohn Birrell break; 8571673e404SJohn Birrell case CTF_K_ENUM: 8581673e404SJohn Birrell dptr += sizeof (ctf_enum_t) * vlen; 8591673e404SJohn Birrell break; 8601673e404SJohn Birrell case CTF_K_UNKNOWN: 8611673e404SJohn Birrell break; 8621673e404SJohn Birrell default: 8631673e404SJohn Birrell parseterminate("Unknown CTF type %d (#%d) at %#x", 864*bdf290cdSMark Johnston kind, count, dptr - data); 8651673e404SJohn Birrell } 8661673e404SJohn Birrell 8671673e404SJohn Birrell dptr += increment; 8681673e404SJohn Birrell count++; 8691673e404SJohn Birrell } 8701673e404SJohn Birrell 8711673e404SJohn Birrell debug(3, "CTF read %d types\n", count); 8721673e404SJohn Birrell 8731673e404SJohn Birrell return (count); 8741673e404SJohn Birrell } 8751673e404SJohn Birrell 8761673e404SJohn Birrell /* 8771673e404SJohn Birrell * Resurrect the labels stored in the CTF data, returning the index associated 8781673e404SJohn Birrell * with a label provided by the caller. There are several cases, outlined 8791673e404SJohn Birrell * below. Note that, given two labels, the one associated with the lesser type 8801673e404SJohn Birrell * index is considered to be older than the other. 8811673e404SJohn Birrell * 8821673e404SJohn Birrell * 1. matchlbl == NULL - return the index of the most recent label. 8831673e404SJohn Birrell * 2. matchlbl == "BASE" - return the index of the oldest label. 8841673e404SJohn Birrell * 3. matchlbl != NULL, but doesn't match any labels in the section - warn 8851673e404SJohn Birrell * the user, and proceed as if matchlbl == "BASE" (for safety). 8861673e404SJohn Birrell * 4. matchlbl != NULL, and matches one of the labels in the section - return 8871673e404SJohn Birrell * the type index associated with the label. 8881673e404SJohn Birrell */ 8891673e404SJohn Birrell static int 8901673e404SJohn Birrell resurrect_labels(ctf_header_t *h, tdata_t *td, caddr_t ctfdata, char *matchlbl) 8911673e404SJohn Birrell { 8921673e404SJohn Birrell caddr_t buf = ctfdata + h->cth_lbloff; 8931673e404SJohn Birrell caddr_t sbuf = ctfdata + h->cth_stroff; 8941673e404SJohn Birrell size_t bufsz = h->cth_objtoff - h->cth_lbloff; 8951673e404SJohn Birrell int lastidx = 0, baseidx = -1; 8964cc75139SJohn Birrell char *baselabel = NULL; 8971673e404SJohn Birrell ctf_lblent_t *ctl; 8984cc75139SJohn Birrell void *v = (void *) buf; 8991673e404SJohn Birrell 9004cc75139SJohn Birrell for (ctl = v; (caddr_t)ctl < buf + bufsz; ctl++) { 9011673e404SJohn Birrell char *label = sbuf + ctl->ctl_label; 9021673e404SJohn Birrell 9031673e404SJohn Birrell lastidx = ctl->ctl_typeidx; 9041673e404SJohn Birrell 9051673e404SJohn Birrell debug(3, "Resurrected label %s type idx %d\n", label, lastidx); 9061673e404SJohn Birrell 9071673e404SJohn Birrell tdata_label_add(td, label, lastidx); 9081673e404SJohn Birrell 9091673e404SJohn Birrell if (baseidx == -1) { 9101673e404SJohn Birrell baseidx = lastidx; 9111673e404SJohn Birrell baselabel = label; 9121673e404SJohn Birrell if (matchlbl != NULL && streq(matchlbl, "BASE")) 9131673e404SJohn Birrell return (lastidx); 9141673e404SJohn Birrell } 9151673e404SJohn Birrell 9161673e404SJohn Birrell if (matchlbl != NULL && streq(label, matchlbl)) 9171673e404SJohn Birrell return (lastidx); 9181673e404SJohn Birrell } 9191673e404SJohn Birrell 9201673e404SJohn Birrell if (matchlbl != NULL) { 9211673e404SJohn Birrell /* User provided a label that didn't match */ 9221673e404SJohn Birrell warning("%s: Cannot find label `%s' - using base (%s)\n", 9231673e404SJohn Birrell curfile, matchlbl, (baselabel ? baselabel : "NONE")); 9241673e404SJohn Birrell 9251673e404SJohn Birrell tdata_label_free(td); 9261673e404SJohn Birrell tdata_label_add(td, baselabel, baseidx); 9271673e404SJohn Birrell 9281673e404SJohn Birrell return (baseidx); 9291673e404SJohn Birrell } 9301673e404SJohn Birrell 9311673e404SJohn Birrell return (lastidx); 9321673e404SJohn Birrell } 9331673e404SJohn Birrell 9341673e404SJohn Birrell static void 9351673e404SJohn Birrell resurrect_objects(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize, 9361673e404SJohn Birrell caddr_t ctfdata, symit_data_t *si) 9371673e404SJohn Birrell { 9381673e404SJohn Birrell caddr_t buf = ctfdata + h->cth_objtoff; 9391673e404SJohn Birrell size_t bufsz = h->cth_funcoff - h->cth_objtoff; 9401673e404SJohn Birrell caddr_t dptr; 941*bdf290cdSMark Johnston size_t idwidth; 942*bdf290cdSMark Johnston 943*bdf290cdSMark Johnston idwidth = h->cth_version == CTF_VERSION_2 ? 2 : 4; 9441673e404SJohn Birrell 9451673e404SJohn Birrell symit_reset(si); 946*bdf290cdSMark Johnston for (dptr = buf; dptr < buf + bufsz; dptr += idwidth) { 947*bdf290cdSMark Johnston uint32_t id = 0; 948*bdf290cdSMark Johnston 949*bdf290cdSMark Johnston memcpy(&id, (void *) dptr, idwidth); 9501673e404SJohn Birrell iidesc_t *ii; 9511673e404SJohn Birrell GElf_Sym *sym; 9521673e404SJohn Birrell 9531673e404SJohn Birrell if (!(sym = symit_next(si, STT_OBJECT)) && id != 0) { 9541673e404SJohn Birrell parseterminate( 9551673e404SJohn Birrell "Unexpected end of object symbols at %x of %x", 9561673e404SJohn Birrell dptr - buf, bufsz); 9571673e404SJohn Birrell } 9581673e404SJohn Birrell 9591673e404SJohn Birrell if (id == 0) { 9601673e404SJohn Birrell debug(3, "Skipping null object\n"); 9611673e404SJohn Birrell continue; 962*bdf290cdSMark Johnston } else if (id >= (uint_t)tdsize) { 9631673e404SJohn Birrell parseterminate("Reference to invalid type %d", id); 9641673e404SJohn Birrell } 9651673e404SJohn Birrell 9661673e404SJohn Birrell ii = iidesc_new(symit_name(si)); 9671673e404SJohn Birrell ii->ii_dtype = tdarr[id]; 9681673e404SJohn Birrell if (GELF_ST_BIND(sym->st_info) == STB_LOCAL) { 9691673e404SJohn Birrell ii->ii_type = II_SVAR; 9701673e404SJohn Birrell ii->ii_owner = xstrdup(symit_curfile(si)); 9711673e404SJohn Birrell } else 9721673e404SJohn Birrell ii->ii_type = II_GVAR; 9731673e404SJohn Birrell hash_add(td->td_iihash, ii); 9741673e404SJohn Birrell 9751673e404SJohn Birrell debug(3, "Resurrected %s object %s (%d) from %s\n", 9761673e404SJohn Birrell (ii->ii_type == II_GVAR ? "global" : "static"), 9771673e404SJohn Birrell ii->ii_name, id, (ii->ii_owner ? ii->ii_owner : "(none)")); 9781673e404SJohn Birrell } 9791673e404SJohn Birrell } 9801673e404SJohn Birrell 9811673e404SJohn Birrell static void 9821673e404SJohn Birrell resurrect_functions(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize, 9831673e404SJohn Birrell caddr_t ctfdata, symit_data_t *si) 9841673e404SJohn Birrell { 9851673e404SJohn Birrell caddr_t buf = ctfdata + h->cth_funcoff; 9861673e404SJohn Birrell size_t bufsz = h->cth_typeoff - h->cth_funcoff; 987*bdf290cdSMark Johnston size_t idwidth; 9881673e404SJohn Birrell caddr_t dptr = buf; 9891673e404SJohn Birrell iidesc_t *ii; 9901673e404SJohn Birrell GElf_Sym *sym; 9911673e404SJohn Birrell int i; 9921673e404SJohn Birrell 993*bdf290cdSMark Johnston idwidth = h->cth_version == CTF_VERSION_2 ? 2 : 4; 994*bdf290cdSMark Johnston 9951673e404SJohn Birrell symit_reset(si); 9961673e404SJohn Birrell while (dptr < buf + bufsz) { 997*bdf290cdSMark Johnston uint32_t id, info, retid; 998*bdf290cdSMark Johnston 999*bdf290cdSMark Johnston info = 0; 1000*bdf290cdSMark Johnston memcpy(&info, (void *) dptr, idwidth); 1001*bdf290cdSMark Johnston dptr += idwidth; 10021673e404SJohn Birrell 10031673e404SJohn Birrell if (!(sym = symit_next(si, STT_FUNC)) && info != 0) 10041673e404SJohn Birrell parseterminate("Unexpected end of function symbols"); 10051673e404SJohn Birrell 10061673e404SJohn Birrell if (info == 0) { 10071673e404SJohn Birrell debug(3, "Skipping null function (%s)\n", 10081673e404SJohn Birrell symit_name(si)); 10091673e404SJohn Birrell continue; 10101673e404SJohn Birrell } 10111673e404SJohn Birrell 1012*bdf290cdSMark Johnston retid = 0; 1013*bdf290cdSMark Johnston memcpy(&retid, (void *) dptr, idwidth); 1014*bdf290cdSMark Johnston dptr += idwidth; 10151673e404SJohn Birrell 1016*bdf290cdSMark Johnston if (retid >= (uint_t)tdsize) 10171673e404SJohn Birrell parseterminate("Reference to invalid type %d", retid); 10181673e404SJohn Birrell 10191673e404SJohn Birrell ii = iidesc_new(symit_name(si)); 10201673e404SJohn Birrell ii->ii_dtype = tdarr[retid]; 10211673e404SJohn Birrell if (GELF_ST_BIND(sym->st_info) == STB_LOCAL) { 10221673e404SJohn Birrell ii->ii_type = II_SFUN; 10231673e404SJohn Birrell ii->ii_owner = xstrdup(symit_curfile(si)); 10241673e404SJohn Birrell } else 10251673e404SJohn Birrell ii->ii_type = II_GFUN; 1026*bdf290cdSMark Johnston if (h->cth_version == CTF_VERSION_2) 1027*bdf290cdSMark Johnston ii->ii_nargs = CTF_V2_INFO_VLEN(info); 1028*bdf290cdSMark Johnston else 1029*bdf290cdSMark Johnston ii->ii_nargs = CTF_V3_INFO_VLEN(info); 10301673e404SJohn Birrell if (ii->ii_nargs) 10311673e404SJohn Birrell ii->ii_args = 10321673e404SJohn Birrell xmalloc(sizeof (tdesc_t *) * ii->ii_nargs); 10331673e404SJohn Birrell 1034*bdf290cdSMark Johnston for (i = 0; i < ii->ii_nargs; i++, dptr += idwidth) { 1035*bdf290cdSMark Johnston id = 0; 1036*bdf290cdSMark Johnston memcpy(&id, (void *) dptr, idwidth); 1037*bdf290cdSMark Johnston if (id >= (uint_t)tdsize) 10381673e404SJohn Birrell parseterminate("Reference to invalid type %d", 10391673e404SJohn Birrell id); 10401673e404SJohn Birrell ii->ii_args[i] = tdarr[id]; 10411673e404SJohn Birrell } 10421673e404SJohn Birrell 10431673e404SJohn Birrell if (ii->ii_nargs && ii->ii_args[ii->ii_nargs - 1] == NULL) { 10441673e404SJohn Birrell ii->ii_nargs--; 10451673e404SJohn Birrell ii->ii_vargs = 1; 10461673e404SJohn Birrell } 10471673e404SJohn Birrell 10481673e404SJohn Birrell hash_add(td->td_iihash, ii); 10491673e404SJohn Birrell 10501673e404SJohn Birrell debug(3, "Resurrected %s function %s (%d, %d args)\n", 10511673e404SJohn Birrell (ii->ii_type == II_GFUN ? "global" : "static"), 10521673e404SJohn Birrell ii->ii_name, retid, ii->ii_nargs); 10531673e404SJohn Birrell } 10541673e404SJohn Birrell } 10551673e404SJohn Birrell 10561673e404SJohn Birrell static void 10571673e404SJohn Birrell resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize, 10581673e404SJohn Birrell caddr_t ctfdata, int maxid) 10591673e404SJohn Birrell { 10601673e404SJohn Birrell caddr_t buf = ctfdata + h->cth_typeoff; 10611673e404SJohn Birrell size_t bufsz = h->cth_stroff - h->cth_typeoff; 10621673e404SJohn Birrell caddr_t sbuf = ctfdata + h->cth_stroff; 10631673e404SJohn Birrell caddr_t dptr = buf; 10641673e404SJohn Birrell tdesc_t *tdp; 10651673e404SJohn Birrell uint_t data; 10661673e404SJohn Birrell uint_t encoding; 1067*bdf290cdSMark Johnston size_t idwidth, size, increment; 10681673e404SJohn Birrell int tcnt; 10691673e404SJohn Birrell int iicnt = 0; 10701673e404SJohn Birrell tid_t tid, argid; 1071*bdf290cdSMark Johnston int isroot, kind, vlen; 1072*bdf290cdSMark Johnston int i, version; 10731673e404SJohn Birrell 10741673e404SJohn Birrell elist_t **epp; 10751673e404SJohn Birrell mlist_t **mpp; 10761673e404SJohn Birrell intr_t *ip; 10771673e404SJohn Birrell 1078*bdf290cdSMark Johnston version = h->cth_version; 1079*bdf290cdSMark Johnston idwidth = version == CTF_VERSION_2 ? 2 : 4; 10801673e404SJohn Birrell 10811673e404SJohn Birrell /* 10821673e404SJohn Birrell * A maxid of zero indicates a request to resurrect all types, so reset 10831673e404SJohn Birrell * maxid to the maximum type id. 10841673e404SJohn Birrell */ 1085*bdf290cdSMark Johnston if (maxid == 0) { 1086*bdf290cdSMark Johnston maxid = version == CTF_VERSION_2 ? 1087*bdf290cdSMark Johnston CTF_V2_MAX_TYPE : CTF_V3_MAX_TYPE; 1088*bdf290cdSMark Johnston } 10891673e404SJohn Birrell 10901673e404SJohn Birrell for (dptr = buf, tcnt = 0, tid = 1; dptr < buf + bufsz; tcnt++, tid++) { 1091*bdf290cdSMark Johnston ctf_enum_t *cte; 1092*bdf290cdSMark Johnston uint_t name, type; 1093*bdf290cdSMark Johnston void *v; 1094*bdf290cdSMark Johnston 10951673e404SJohn Birrell if (tid > maxid) 10961673e404SJohn Birrell break; 10971673e404SJohn Birrell 10981673e404SJohn Birrell if (tid >= tdsize) 10991673e404SJohn Birrell parseterminate("Reference to invalid type %d", tid); 11001673e404SJohn Birrell 1101*bdf290cdSMark Johnston get_ctt_info(h, dptr, &kind, &vlen, &isroot); 1102*bdf290cdSMark Johnston get_ctt_size(h, dptr, &size, &increment); 1103*bdf290cdSMark Johnston if (version == CTF_VERSION_2) { 1104*bdf290cdSMark Johnston struct ctf_type_v2 *ctt = (void *) dptr; 11051673e404SJohn Birrell 1106*bdf290cdSMark Johnston name = ctt->ctt_name; 1107*bdf290cdSMark Johnston type = ctt->ctt_type; 1108*bdf290cdSMark Johnston } else { 1109*bdf290cdSMark Johnston struct ctf_type_v3 *ctt = (void *) dptr; 1110*bdf290cdSMark Johnston 1111*bdf290cdSMark Johnston name = ctt->ctt_name; 1112*bdf290cdSMark Johnston type = ctt->ctt_type; 1113*bdf290cdSMark Johnston } 11141673e404SJohn Birrell dptr += increment; 11151673e404SJohn Birrell 11161673e404SJohn Birrell tdp = tdarr[tid]; 11171673e404SJohn Birrell 1118*bdf290cdSMark Johnston if (CTF_NAME_STID(name) != CTF_STRTAB_0) 11191673e404SJohn Birrell parseterminate( 11201673e404SJohn Birrell "Unable to cope with non-zero strtab id"); 1121*bdf290cdSMark Johnston if (CTF_NAME_OFFSET(name) != 0) { 1122*bdf290cdSMark Johnston tdp->t_name = xstrdup(sbuf + CTF_NAME_OFFSET(name)); 11231673e404SJohn Birrell } else 11241673e404SJohn Birrell tdp->t_name = NULL; 11251673e404SJohn Birrell 11261673e404SJohn Birrell switch (kind) { 11271673e404SJohn Birrell case CTF_K_INTEGER: 11281673e404SJohn Birrell tdp->t_type = INTRINSIC; 11291673e404SJohn Birrell tdp->t_size = size; 11301673e404SJohn Birrell 11314cc75139SJohn Birrell v = (void *) dptr; 11324cc75139SJohn Birrell data = *((uint_t *)v); 11331673e404SJohn Birrell dptr += sizeof (uint_t); 11341673e404SJohn Birrell encoding = CTF_INT_ENCODING(data); 11351673e404SJohn Birrell 11361673e404SJohn Birrell ip = xmalloc(sizeof (intr_t)); 11371673e404SJohn Birrell ip->intr_type = INTR_INT; 11381673e404SJohn Birrell ip->intr_signed = (encoding & CTF_INT_SIGNED) ? 1 : 0; 11391673e404SJohn Birrell 11401673e404SJohn Birrell if (encoding & CTF_INT_CHAR) 11411673e404SJohn Birrell ip->intr_iformat = 'c'; 11421673e404SJohn Birrell else if (encoding & CTF_INT_BOOL) 11431673e404SJohn Birrell ip->intr_iformat = 'b'; 11441673e404SJohn Birrell else if (encoding & CTF_INT_VARARGS) 11451673e404SJohn Birrell ip->intr_iformat = 'v'; 11461673e404SJohn Birrell else 11471673e404SJohn Birrell ip->intr_iformat = '\0'; 11481673e404SJohn Birrell 11491673e404SJohn Birrell ip->intr_offset = CTF_INT_OFFSET(data); 11501673e404SJohn Birrell ip->intr_nbits = CTF_INT_BITS(data); 11511673e404SJohn Birrell tdp->t_intr = ip; 11521673e404SJohn Birrell break; 11531673e404SJohn Birrell 11541673e404SJohn Birrell case CTF_K_FLOAT: 11551673e404SJohn Birrell tdp->t_type = INTRINSIC; 11561673e404SJohn Birrell tdp->t_size = size; 11571673e404SJohn Birrell 11584cc75139SJohn Birrell v = (void *) dptr; 11594cc75139SJohn Birrell data = *((uint_t *)v); 11601673e404SJohn Birrell dptr += sizeof (uint_t); 11611673e404SJohn Birrell 11621673e404SJohn Birrell ip = xcalloc(sizeof (intr_t)); 11631673e404SJohn Birrell ip->intr_type = INTR_REAL; 11641673e404SJohn Birrell ip->intr_fformat = CTF_FP_ENCODING(data); 11651673e404SJohn Birrell ip->intr_offset = CTF_FP_OFFSET(data); 11661673e404SJohn Birrell ip->intr_nbits = CTF_FP_BITS(data); 11671673e404SJohn Birrell tdp->t_intr = ip; 11681673e404SJohn Birrell break; 11691673e404SJohn Birrell 11701673e404SJohn Birrell case CTF_K_POINTER: 11711673e404SJohn Birrell tdp->t_type = POINTER; 1172*bdf290cdSMark Johnston tdp->t_tdesc = tdarr[type]; 11731673e404SJohn Birrell break; 11741673e404SJohn Birrell 1175*bdf290cdSMark Johnston case CTF_K_ARRAY: { 1176*bdf290cdSMark Johnston uint_t contents, index, nelems; 1177*bdf290cdSMark Johnston 11781673e404SJohn Birrell tdp->t_type = ARRAY; 11791673e404SJohn Birrell tdp->t_size = size; 11801673e404SJohn Birrell 1181*bdf290cdSMark Johnston if (version == CTF_VERSION_2) { 1182*bdf290cdSMark Johnston struct ctf_array_v2 *cta = (void *) dptr; 1183*bdf290cdSMark Johnston contents = cta->cta_contents; 1184*bdf290cdSMark Johnston index = cta->cta_index; 1185*bdf290cdSMark Johnston nelems = cta->cta_nelems; 1186*bdf290cdSMark Johnston dptr += sizeof (*cta); 1187*bdf290cdSMark Johnston } else { 1188*bdf290cdSMark Johnston struct ctf_array_v3 *cta = (void *) dptr; 1189*bdf290cdSMark Johnston contents = cta->cta_contents; 1190*bdf290cdSMark Johnston index = cta->cta_index; 1191*bdf290cdSMark Johnston nelems = cta->cta_nelems; 1192*bdf290cdSMark Johnston dptr += sizeof (*cta); 1193*bdf290cdSMark Johnston } 11941673e404SJohn Birrell 11951673e404SJohn Birrell tdp->t_ardef = xmalloc(sizeof (ardef_t)); 1196*bdf290cdSMark Johnston tdp->t_ardef->ad_contents = tdarr[contents]; 1197*bdf290cdSMark Johnston tdp->t_ardef->ad_idxtype = tdarr[index]; 1198*bdf290cdSMark Johnston tdp->t_ardef->ad_nelems = nelems; 11991673e404SJohn Birrell break; 1200*bdf290cdSMark Johnston } 12011673e404SJohn Birrell 12021673e404SJohn Birrell case CTF_K_STRUCT: 1203*bdf290cdSMark Johnston case CTF_K_UNION: { 12041673e404SJohn Birrell tdp->t_type = (kind == CTF_K_STRUCT ? STRUCT : UNION); 12051673e404SJohn Birrell tdp->t_size = size; 12061673e404SJohn Birrell 1207*bdf290cdSMark Johnston if (version == CTF_VERSION_2) { 1208*bdf290cdSMark Johnston if (size < CTF_V2_LSTRUCT_THRESH) { 12091673e404SJohn Birrell for (i = 0, mpp = &tdp->t_members; i < vlen; 12101673e404SJohn Birrell i++, mpp = &((*mpp)->ml_next)) { 12114cc75139SJohn Birrell v = (void *) dptr; 1212*bdf290cdSMark Johnston struct ctf_member_v2 *ctm = v; 1213*bdf290cdSMark Johnston dptr += sizeof (struct ctf_member_v2); 12141673e404SJohn Birrell 12151673e404SJohn Birrell *mpp = xmalloc(sizeof (mlist_t)); 12161673e404SJohn Birrell (*mpp)->ml_name = xstrdup(sbuf + 12171673e404SJohn Birrell ctm->ctm_name); 12181673e404SJohn Birrell (*mpp)->ml_type = tdarr[ctm->ctm_type]; 12191673e404SJohn Birrell (*mpp)->ml_offset = ctm->ctm_offset; 12201673e404SJohn Birrell (*mpp)->ml_size = 0; 12211673e404SJohn Birrell } 12221673e404SJohn Birrell } else { 12231673e404SJohn Birrell for (i = 0, mpp = &tdp->t_members; i < vlen; 12241673e404SJohn Birrell i++, mpp = &((*mpp)->ml_next)) { 12254cc75139SJohn Birrell v = (void *) dptr; 1226*bdf290cdSMark Johnston struct ctf_lmember_v2 *ctlm = v; 1227*bdf290cdSMark Johnston dptr += sizeof (struct ctf_lmember_v2); 12281673e404SJohn Birrell 12291673e404SJohn Birrell *mpp = xmalloc(sizeof (mlist_t)); 12301673e404SJohn Birrell (*mpp)->ml_name = xstrdup(sbuf + 12311673e404SJohn Birrell ctlm->ctlm_name); 12321673e404SJohn Birrell (*mpp)->ml_type = 12331673e404SJohn Birrell tdarr[ctlm->ctlm_type]; 12341673e404SJohn Birrell (*mpp)->ml_offset = 12351673e404SJohn Birrell (int)CTF_LMEM_OFFSET(ctlm); 12361673e404SJohn Birrell (*mpp)->ml_size = 0; 12371673e404SJohn Birrell } 12381673e404SJohn Birrell } 1239*bdf290cdSMark Johnston } else { 1240*bdf290cdSMark Johnston if (size < CTF_V3_LSTRUCT_THRESH) { 1241*bdf290cdSMark Johnston for (i = 0, mpp = &tdp->t_members; i < vlen; 1242*bdf290cdSMark Johnston i++, mpp = &((*mpp)->ml_next)) { 1243*bdf290cdSMark Johnston v = (void *) dptr; 1244*bdf290cdSMark Johnston struct ctf_member_v3 *ctm = v; 1245*bdf290cdSMark Johnston dptr += sizeof (struct ctf_member_v3); 1246*bdf290cdSMark Johnston 1247*bdf290cdSMark Johnston *mpp = xmalloc(sizeof (mlist_t)); 1248*bdf290cdSMark Johnston (*mpp)->ml_name = xstrdup(sbuf + 1249*bdf290cdSMark Johnston ctm->ctm_name); 1250*bdf290cdSMark Johnston (*mpp)->ml_type = tdarr[ctm->ctm_type]; 1251*bdf290cdSMark Johnston (*mpp)->ml_offset = ctm->ctm_offset; 1252*bdf290cdSMark Johnston (*mpp)->ml_size = 0; 1253*bdf290cdSMark Johnston } 1254*bdf290cdSMark Johnston } else { 1255*bdf290cdSMark Johnston for (i = 0, mpp = &tdp->t_members; i < vlen; 1256*bdf290cdSMark Johnston i++, mpp = &((*mpp)->ml_next)) { 1257*bdf290cdSMark Johnston v = (void *) dptr; 1258*bdf290cdSMark Johnston struct ctf_lmember_v3 *ctlm = v; 1259*bdf290cdSMark Johnston dptr += sizeof (struct ctf_lmember_v3); 1260*bdf290cdSMark Johnston 1261*bdf290cdSMark Johnston *mpp = xmalloc(sizeof (mlist_t)); 1262*bdf290cdSMark Johnston (*mpp)->ml_name = xstrdup(sbuf + 1263*bdf290cdSMark Johnston ctlm->ctlm_name); 1264*bdf290cdSMark Johnston (*mpp)->ml_type = 1265*bdf290cdSMark Johnston tdarr[ctlm->ctlm_type]; 1266*bdf290cdSMark Johnston (*mpp)->ml_offset = 1267*bdf290cdSMark Johnston (int)CTF_LMEM_OFFSET(ctlm); 1268*bdf290cdSMark Johnston (*mpp)->ml_size = 0; 1269*bdf290cdSMark Johnston } 1270*bdf290cdSMark Johnston } 1271*bdf290cdSMark Johnston } 12721673e404SJohn Birrell 12731673e404SJohn Birrell *mpp = NULL; 12741673e404SJohn Birrell break; 1275*bdf290cdSMark Johnston } 12761673e404SJohn Birrell 12771673e404SJohn Birrell case CTF_K_ENUM: 12781673e404SJohn Birrell tdp->t_type = ENUM; 12791673e404SJohn Birrell tdp->t_size = size; 12801673e404SJohn Birrell 12811673e404SJohn Birrell for (i = 0, epp = &tdp->t_emem; i < vlen; 12821673e404SJohn Birrell i++, epp = &((*epp)->el_next)) { 12834cc75139SJohn Birrell v = (void *) dptr; 12844cc75139SJohn Birrell cte = v; 12851673e404SJohn Birrell dptr += sizeof (ctf_enum_t); 12861673e404SJohn Birrell 12871673e404SJohn Birrell *epp = xmalloc(sizeof (elist_t)); 12881673e404SJohn Birrell (*epp)->el_name = xstrdup(sbuf + cte->cte_name); 12891673e404SJohn Birrell (*epp)->el_number = cte->cte_value; 12901673e404SJohn Birrell } 12911673e404SJohn Birrell *epp = NULL; 12921673e404SJohn Birrell break; 12931673e404SJohn Birrell 12941673e404SJohn Birrell case CTF_K_FORWARD: 12951673e404SJohn Birrell tdp->t_type = FORWARD; 12961673e404SJohn Birrell list_add(&td->td_fwdlist, tdp); 12971673e404SJohn Birrell break; 12981673e404SJohn Birrell 12991673e404SJohn Birrell case CTF_K_TYPEDEF: 13001673e404SJohn Birrell tdp->t_type = TYPEDEF; 1301*bdf290cdSMark Johnston tdp->t_tdesc = tdarr[type]; 13021673e404SJohn Birrell break; 13031673e404SJohn Birrell 13041673e404SJohn Birrell case CTF_K_VOLATILE: 13051673e404SJohn Birrell tdp->t_type = VOLATILE; 1306*bdf290cdSMark Johnston tdp->t_tdesc = tdarr[type]; 13071673e404SJohn Birrell break; 13081673e404SJohn Birrell 13091673e404SJohn Birrell case CTF_K_CONST: 13101673e404SJohn Birrell tdp->t_type = CONST; 1311*bdf290cdSMark Johnston tdp->t_tdesc = tdarr[type]; 13121673e404SJohn Birrell break; 13131673e404SJohn Birrell 13141673e404SJohn Birrell case CTF_K_FUNCTION: 13151673e404SJohn Birrell tdp->t_type = FUNCTION; 13161673e404SJohn Birrell tdp->t_fndef = xcalloc(sizeof (fndef_t)); 1317*bdf290cdSMark Johnston tdp->t_fndef->fn_ret = tdarr[type]; 13181673e404SJohn Birrell 1319*bdf290cdSMark Johnston v = (void *) (dptr + (idwidth * (vlen - 1))); 1320*bdf290cdSMark Johnston if (vlen > 0 && *(uint_t *)v == 0) 13211673e404SJohn Birrell tdp->t_fndef->fn_vargs = 1; 13221673e404SJohn Birrell 13231673e404SJohn Birrell tdp->t_fndef->fn_nargs = vlen - tdp->t_fndef->fn_vargs; 13241673e404SJohn Birrell tdp->t_fndef->fn_args = xcalloc(sizeof (tdesc_t) * 13251673e404SJohn Birrell vlen - tdp->t_fndef->fn_vargs); 13261673e404SJohn Birrell 13271673e404SJohn Birrell for (i = 0; i < vlen; i++) { 13284cc75139SJohn Birrell v = (void *) dptr; 1329*bdf290cdSMark Johnston memcpy(&argid, v, idwidth); 1330*bdf290cdSMark Johnston dptr += idwidth; 13311673e404SJohn Birrell 13321673e404SJohn Birrell if (argid != 0) 13331673e404SJohn Birrell tdp->t_fndef->fn_args[i] = tdarr[argid]; 13341673e404SJohn Birrell } 13351673e404SJohn Birrell 1336*bdf290cdSMark Johnston dptr = roundup2(dptr, 4); 13371673e404SJohn Birrell break; 13381673e404SJohn Birrell 13391673e404SJohn Birrell case CTF_K_RESTRICT: 13401673e404SJohn Birrell tdp->t_type = RESTRICT; 1341*bdf290cdSMark Johnston tdp->t_tdesc = tdarr[type]; 13421673e404SJohn Birrell break; 13431673e404SJohn Birrell 13441673e404SJohn Birrell case CTF_K_UNKNOWN: 13451673e404SJohn Birrell break; 13461673e404SJohn Birrell 13471673e404SJohn Birrell default: 13481673e404SJohn Birrell warning("Can't parse unknown CTF type %d\n", kind); 13491673e404SJohn Birrell } 13501673e404SJohn Birrell 1351*bdf290cdSMark Johnston if (isroot) { 13521673e404SJohn Birrell iidesc_t *ii = iidesc_new(tdp->t_name); 13531673e404SJohn Birrell if (tdp->t_type == STRUCT || tdp->t_type == UNION || 13541673e404SJohn Birrell tdp->t_type == ENUM) 13551673e404SJohn Birrell ii->ii_type = II_SOU; 13561673e404SJohn Birrell else 13571673e404SJohn Birrell ii->ii_type = II_TYPE; 13581673e404SJohn Birrell ii->ii_dtype = tdp; 13591673e404SJohn Birrell hash_add(td->td_iihash, ii); 13601673e404SJohn Birrell 13611673e404SJohn Birrell iicnt++; 13621673e404SJohn Birrell } 13631673e404SJohn Birrell 13641673e404SJohn Birrell debug(3, "Resurrected %d %stype %s (%d)\n", tdp->t_type, 1365*bdf290cdSMark Johnston (isroot ? "root " : ""), tdesc_name(tdp), tdp->t_id); 13661673e404SJohn Birrell } 13671673e404SJohn Birrell 13681673e404SJohn Birrell debug(3, "Resurrected %d types (%d were roots)\n", tcnt, iicnt); 13691673e404SJohn Birrell } 13701673e404SJohn Birrell 13711673e404SJohn Birrell /* 13721673e404SJohn Birrell * For lack of other inspiration, we're going to take the boring route. We 13731673e404SJohn Birrell * count the number of types. This lets us malloc that many tdesc structs 13741673e404SJohn Birrell * before we start filling them in. This has the advantage of allowing us to 13751673e404SJohn Birrell * avoid a merge-esque remap step. 13761673e404SJohn Birrell */ 13771673e404SJohn Birrell static tdata_t * 13781673e404SJohn Birrell ctf_parse(ctf_header_t *h, caddr_t buf, symit_data_t *si, char *label) 13791673e404SJohn Birrell { 13801673e404SJohn Birrell tdata_t *td = tdata_new(); 13811673e404SJohn Birrell tdesc_t **tdarr; 138269718b78SPedro F. Giffuni int ntypes = count_types(h, buf); 13831673e404SJohn Birrell int idx, i; 13841673e404SJohn Birrell 13851673e404SJohn Birrell /* shudder */ 13861673e404SJohn Birrell tdarr = xcalloc(sizeof (tdesc_t *) * (ntypes + 1)); 13871673e404SJohn Birrell tdarr[0] = NULL; 13881673e404SJohn Birrell for (i = 1; i <= ntypes; i++) { 13891673e404SJohn Birrell tdarr[i] = xcalloc(sizeof (tdesc_t)); 13901673e404SJohn Birrell tdarr[i]->t_id = i; 13911673e404SJohn Birrell } 13921673e404SJohn Birrell 13931673e404SJohn Birrell td->td_parlabel = xstrdup(buf + h->cth_stroff + h->cth_parlabel); 13941673e404SJohn Birrell 13951673e404SJohn Birrell /* we have the technology - we can rebuild them */ 13961673e404SJohn Birrell idx = resurrect_labels(h, td, buf, label); 13971673e404SJohn Birrell 13981673e404SJohn Birrell resurrect_objects(h, td, tdarr, ntypes + 1, buf, si); 13991673e404SJohn Birrell resurrect_functions(h, td, tdarr, ntypes + 1, buf, si); 14001673e404SJohn Birrell resurrect_types(h, td, tdarr, ntypes + 1, buf, idx); 14011673e404SJohn Birrell 14021673e404SJohn Birrell free(tdarr); 14031673e404SJohn Birrell 14041673e404SJohn Birrell td->td_nextid = ntypes + 1; 14051673e404SJohn Birrell 14061673e404SJohn Birrell return (td); 14071673e404SJohn Birrell } 14081673e404SJohn Birrell 14091673e404SJohn Birrell static size_t 14101673e404SJohn Birrell decompress_ctf(caddr_t cbuf, size_t cbufsz, caddr_t dbuf, size_t dbufsz) 14111673e404SJohn Birrell { 14121673e404SJohn Birrell z_stream zstr; 14131673e404SJohn Birrell int rc; 14141673e404SJohn Birrell 14151673e404SJohn Birrell zstr.zalloc = (alloc_func)0; 14161673e404SJohn Birrell zstr.zfree = (free_func)0; 14171673e404SJohn Birrell zstr.opaque = (voidpf)0; 14181673e404SJohn Birrell 14191673e404SJohn Birrell zstr.next_in = (Bytef *)cbuf; 14201673e404SJohn Birrell zstr.avail_in = cbufsz; 14211673e404SJohn Birrell zstr.next_out = (Bytef *)dbuf; 14221673e404SJohn Birrell zstr.avail_out = dbufsz; 14231673e404SJohn Birrell 14241673e404SJohn Birrell if ((rc = inflateInit(&zstr)) != Z_OK || 14251673e404SJohn Birrell (rc = inflate(&zstr, Z_NO_FLUSH)) != Z_STREAM_END || 14261673e404SJohn Birrell (rc = inflateEnd(&zstr)) != Z_OK) { 14271673e404SJohn Birrell warning("CTF decompress zlib error %s\n", zError(rc)); 14284cc75139SJohn Birrell return (0); 14291673e404SJohn Birrell } 14301673e404SJohn Birrell 14311673e404SJohn Birrell debug(3, "reflated %lu bytes to %lu, pointer at %d\n", 14321673e404SJohn Birrell zstr.total_in, zstr.total_out, (caddr_t)zstr.next_in - cbuf); 14331673e404SJohn Birrell 14341673e404SJohn Birrell return (zstr.total_out); 14351673e404SJohn Birrell } 14361673e404SJohn Birrell 14371673e404SJohn Birrell /* 14381673e404SJohn Birrell * Reconstruct the type tree from a given buffer of CTF data. Only the types 14391673e404SJohn Birrell * up to the type associated with the provided label, inclusive, will be 14401673e404SJohn Birrell * reconstructed. If a NULL label is provided, all types will be reconstructed. 14411673e404SJohn Birrell * 14421673e404SJohn Birrell * This function won't work on files that have been uniquified. 14431673e404SJohn Birrell */ 14441673e404SJohn Birrell tdata_t * 14451673e404SJohn Birrell ctf_load(char *file, caddr_t buf, size_t bufsz, symit_data_t *si, char *label) 14461673e404SJohn Birrell { 14471673e404SJohn Birrell ctf_header_t *h; 14481673e404SJohn Birrell caddr_t ctfdata; 14491673e404SJohn Birrell size_t ctfdatasz; 14501673e404SJohn Birrell tdata_t *td; 14511673e404SJohn Birrell 14521673e404SJohn Birrell curfile = file; 14531673e404SJohn Birrell 14541673e404SJohn Birrell if (bufsz < sizeof (ctf_header_t)) 14551673e404SJohn Birrell parseterminate("Corrupt CTF - short header"); 14561673e404SJohn Birrell 14574cc75139SJohn Birrell void *v = (void *) buf; 14584cc75139SJohn Birrell h = v; 14591673e404SJohn Birrell buf += sizeof (ctf_header_t); 14601673e404SJohn Birrell bufsz -= sizeof (ctf_header_t); 14611673e404SJohn Birrell 14621673e404SJohn Birrell if (h->cth_magic != CTF_MAGIC) 14631673e404SJohn Birrell parseterminate("Corrupt CTF - bad magic 0x%x", h->cth_magic); 14641673e404SJohn Birrell 1465*bdf290cdSMark Johnston if (h->cth_version != CTF_VERSION_2 && h->cth_version != CTF_VERSION_3) 14661673e404SJohn Birrell parseterminate("Unknown CTF version %d", h->cth_version); 14671673e404SJohn Birrell 14681673e404SJohn Birrell ctfdatasz = h->cth_stroff + h->cth_strlen; 14691673e404SJohn Birrell if (h->cth_flags & CTF_F_COMPRESS) { 14701673e404SJohn Birrell size_t actual; 14711673e404SJohn Birrell 14721673e404SJohn Birrell ctfdata = xmalloc(ctfdatasz); 14731673e404SJohn Birrell if ((actual = decompress_ctf(buf, bufsz, ctfdata, ctfdatasz)) != 14741673e404SJohn Birrell ctfdatasz) { 14751673e404SJohn Birrell parseterminate("Corrupt CTF - short decompression " 14761673e404SJohn Birrell "(was %d, expecting %d)", actual, ctfdatasz); 14771673e404SJohn Birrell } 14781673e404SJohn Birrell } else { 14791673e404SJohn Birrell ctfdata = buf; 14801673e404SJohn Birrell ctfdatasz = bufsz; 14811673e404SJohn Birrell } 14821673e404SJohn Birrell 14831673e404SJohn Birrell td = ctf_parse(h, ctfdata, si, label); 14841673e404SJohn Birrell 14851673e404SJohn Birrell if (h->cth_flags & CTF_F_COMPRESS) 14861673e404SJohn Birrell free(ctfdata); 14871673e404SJohn Birrell 14881673e404SJohn Birrell curfile = NULL; 14891673e404SJohn Birrell 14901673e404SJohn Birrell return (td); 14911673e404SJohn Birrell } 1492