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 */ 611673e404SJohn Birrell int nptent; /* number of processed types */ 621673e404SJohn Birrell int ntholes; /* number of type holes */ 631673e404SJohn Birrell }; 641673e404SJohn Birrell 65a6425ab5SOleksandr Tymoshenko /* 66a6425ab5SOleksandr Tymoshenko * Macros to reverse byte order 67a6425ab5SOleksandr Tymoshenko */ 68a6425ab5SOleksandr Tymoshenko #define BSWAP_8(x) ((x) & 0xff) 69a6425ab5SOleksandr Tymoshenko #define BSWAP_16(x) ((BSWAP_8(x) << 8) | BSWAP_8((x) >> 8)) 70a6425ab5SOleksandr Tymoshenko #define BSWAP_32(x) ((BSWAP_16(x) << 16) | BSWAP_16((x) >> 16)) 71a6425ab5SOleksandr Tymoshenko 72a6425ab5SOleksandr Tymoshenko #define SWAP_16(x) (x) = BSWAP_16(x) 73a6425ab5SOleksandr Tymoshenko #define SWAP_32(x) (x) = BSWAP_32(x) 74a6425ab5SOleksandr Tymoshenko 75a6425ab5SOleksandr Tymoshenko static int target_requires_swap; 76a6425ab5SOleksandr Tymoshenko 771673e404SJohn Birrell /*PRINTFLIKE1*/ 781673e404SJohn Birrell static void 794cc75139SJohn Birrell parseterminate(const char *fmt, ...) 801673e404SJohn Birrell { 811673e404SJohn Birrell static char msgbuf[1024]; /* sigh */ 821673e404SJohn Birrell va_list ap; 831673e404SJohn Birrell 841673e404SJohn Birrell va_start(ap, fmt); 851673e404SJohn Birrell vsnprintf(msgbuf, sizeof (msgbuf), fmt, ap); 861673e404SJohn Birrell va_end(ap); 871673e404SJohn Birrell 881673e404SJohn Birrell terminate("%s: %s\n", curfile, msgbuf); 891673e404SJohn Birrell } 901673e404SJohn Birrell 914cc75139SJohn Birrell static void 921673e404SJohn Birrell ctf_buf_grow(ctf_buf_t *b) 931673e404SJohn Birrell { 941673e404SJohn Birrell off_t ptroff = b->ctb_ptr - b->ctb_base; 951673e404SJohn Birrell 961673e404SJohn Birrell b->ctb_size += CTF_BUF_CHUNK_SIZE; 971673e404SJohn Birrell b->ctb_base = xrealloc(b->ctb_base, b->ctb_size); 981673e404SJohn Birrell b->ctb_end = b->ctb_base + b->ctb_size; 991673e404SJohn Birrell b->ctb_ptr = b->ctb_base + ptroff; 1001673e404SJohn Birrell } 1011673e404SJohn Birrell 1024cc75139SJohn Birrell static ctf_buf_t * 1031673e404SJohn Birrell ctf_buf_new(void) 1041673e404SJohn Birrell { 1051673e404SJohn Birrell ctf_buf_t *b = xcalloc(sizeof (ctf_buf_t)); 1061673e404SJohn Birrell 1071673e404SJohn Birrell strtab_create(&b->ctb_strtab); 1081673e404SJohn Birrell ctf_buf_grow(b); 1091673e404SJohn Birrell 1101673e404SJohn Birrell return (b); 1111673e404SJohn Birrell } 1121673e404SJohn Birrell 1134cc75139SJohn Birrell static void 1141673e404SJohn Birrell ctf_buf_free(ctf_buf_t *b) 1151673e404SJohn Birrell { 1161673e404SJohn Birrell strtab_destroy(&b->ctb_strtab); 1171673e404SJohn Birrell free(b->ctb_base); 1181673e404SJohn Birrell free(b); 1191673e404SJohn Birrell } 1201673e404SJohn Birrell 1214cc75139SJohn Birrell static uint_t 1221673e404SJohn Birrell ctf_buf_cur(ctf_buf_t *b) 1231673e404SJohn Birrell { 1241673e404SJohn Birrell return (b->ctb_ptr - b->ctb_base); 1251673e404SJohn Birrell } 1261673e404SJohn Birrell 1274cc75139SJohn Birrell static void 1284cc75139SJohn Birrell ctf_buf_write(ctf_buf_t *b, void const *p, size_t n) 1291673e404SJohn Birrell { 1301673e404SJohn Birrell size_t len; 1311673e404SJohn Birrell 1321673e404SJohn Birrell while (n != 0) { 1331673e404SJohn Birrell if (b->ctb_ptr == b->ctb_end) 1341673e404SJohn Birrell ctf_buf_grow(b); 1351673e404SJohn Birrell 1361673e404SJohn Birrell len = MIN((size_t)(b->ctb_end - b->ctb_ptr), n); 1371673e404SJohn Birrell bcopy(p, b->ctb_ptr, len); 1381673e404SJohn Birrell b->ctb_ptr += len; 1391673e404SJohn Birrell 1404cc75139SJohn Birrell p = (char const *)p + len; 1411673e404SJohn Birrell n -= len; 1421673e404SJohn Birrell } 1431673e404SJohn Birrell } 1441673e404SJohn Birrell 1451673e404SJohn Birrell static int 1464cc75139SJohn Birrell write_label(void *arg1, void *arg2) 1471673e404SJohn Birrell { 1484cc75139SJohn Birrell labelent_t *le = arg1; 1494cc75139SJohn Birrell ctf_buf_t *b = arg2; 1501673e404SJohn Birrell ctf_lblent_t ctl; 1511673e404SJohn Birrell 1521673e404SJohn Birrell ctl.ctl_label = strtab_insert(&b->ctb_strtab, le->le_name); 1531673e404SJohn Birrell ctl.ctl_typeidx = le->le_idx; 1541673e404SJohn Birrell 155a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 156a6425ab5SOleksandr Tymoshenko SWAP_32(ctl.ctl_label); 157a6425ab5SOleksandr Tymoshenko SWAP_32(ctl.ctl_typeidx); 158a6425ab5SOleksandr Tymoshenko } 159a6425ab5SOleksandr Tymoshenko 1601673e404SJohn Birrell ctf_buf_write(b, &ctl, sizeof (ctl)); 1611673e404SJohn Birrell 1621673e404SJohn Birrell return (1); 1631673e404SJohn Birrell } 1641673e404SJohn Birrell 1651673e404SJohn Birrell static void 1661673e404SJohn Birrell write_objects(iidesc_t *idp, ctf_buf_t *b) 1671673e404SJohn Birrell { 1681673e404SJohn Birrell ushort_t id = (idp ? idp->ii_dtype->t_id : 0); 1691673e404SJohn Birrell 170a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 171a6425ab5SOleksandr Tymoshenko SWAP_16(id); 172a6425ab5SOleksandr Tymoshenko } 173a6425ab5SOleksandr Tymoshenko 174fcb56067SGeorge V. Neville-Neil ctf_buf_write(b, &id, sizeof (id)); 175fcb56067SGeorge V. Neville-Neil 1761673e404SJohn Birrell debug(3, "Wrote object %s (%d)\n", (idp ? idp->ii_name : "(null)"), id); 1771673e404SJohn Birrell } 1781673e404SJohn Birrell 1791673e404SJohn Birrell static void 1801673e404SJohn Birrell write_functions(iidesc_t *idp, ctf_buf_t *b) 1811673e404SJohn Birrell { 1821673e404SJohn Birrell ushort_t fdata[2]; 1831673e404SJohn Birrell ushort_t id; 1841673e404SJohn Birrell int nargs; 1851673e404SJohn Birrell int i; 1861673e404SJohn Birrell 1871673e404SJohn Birrell if (!idp) { 1881673e404SJohn Birrell fdata[0] = 0; 1891673e404SJohn Birrell ctf_buf_write(b, &fdata[0], sizeof (fdata[0])); 1901673e404SJohn Birrell 1911673e404SJohn Birrell debug(3, "Wrote function (null)\n"); 1921673e404SJohn Birrell return; 1931673e404SJohn Birrell } 1941673e404SJohn Birrell 1951673e404SJohn Birrell nargs = idp->ii_nargs + (idp->ii_vargs != 0); 1961670a1c2SRui Paulo 1971670a1c2SRui Paulo if (nargs > CTF_MAX_VLEN) { 1981670a1c2SRui Paulo terminate("function %s has too many args: %d > %d\n", 1991670a1c2SRui Paulo idp->ii_name, nargs, CTF_MAX_VLEN); 2001670a1c2SRui Paulo } 2011670a1c2SRui Paulo 2021673e404SJohn Birrell fdata[0] = CTF_TYPE_INFO(CTF_K_FUNCTION, 1, nargs); 2031673e404SJohn Birrell fdata[1] = idp->ii_dtype->t_id; 204a6425ab5SOleksandr Tymoshenko 205a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 206a6425ab5SOleksandr Tymoshenko SWAP_16(fdata[0]); 207a6425ab5SOleksandr Tymoshenko SWAP_16(fdata[1]); 208a6425ab5SOleksandr Tymoshenko } 209a6425ab5SOleksandr Tymoshenko 2101673e404SJohn Birrell ctf_buf_write(b, fdata, sizeof (fdata)); 2111673e404SJohn Birrell 2121673e404SJohn Birrell for (i = 0; i < idp->ii_nargs; i++) { 2131673e404SJohn Birrell id = idp->ii_args[i]->t_id; 214a6425ab5SOleksandr Tymoshenko 215a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 216a6425ab5SOleksandr Tymoshenko SWAP_16(id); 217a6425ab5SOleksandr Tymoshenko } 218a6425ab5SOleksandr Tymoshenko 2191673e404SJohn Birrell ctf_buf_write(b, &id, sizeof (id)); 2201673e404SJohn Birrell } 2211673e404SJohn Birrell 2221673e404SJohn Birrell if (idp->ii_vargs) { 2231673e404SJohn Birrell id = 0; 2241673e404SJohn Birrell ctf_buf_write(b, &id, sizeof (id)); 2251673e404SJohn Birrell } 2261673e404SJohn Birrell 2271673e404SJohn Birrell debug(3, "Wrote function %s (%d args)\n", idp->ii_name, nargs); 2281673e404SJohn Birrell } 2291673e404SJohn Birrell 2301673e404SJohn Birrell /* 2311673e404SJohn Birrell * Depending on the size of the type being described, either a ctf_stype_t (for 2321673e404SJohn Birrell * types with size < CTF_LSTRUCT_THRESH) or a ctf_type_t (all others) will be 2331673e404SJohn Birrell * written. We isolate the determination here so the rest of the writer code 2341673e404SJohn Birrell * doesn't need to care. 2351673e404SJohn Birrell */ 2361673e404SJohn Birrell static void 2371673e404SJohn Birrell write_sized_type_rec(ctf_buf_t *b, ctf_type_t *ctt, size_t size) 2381673e404SJohn Birrell { 2391673e404SJohn Birrell if (size > CTF_MAX_SIZE) { 2401673e404SJohn Birrell ctt->ctt_size = CTF_LSIZE_SENT; 2411673e404SJohn Birrell ctt->ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size); 2421673e404SJohn Birrell ctt->ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size); 243a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 244a6425ab5SOleksandr Tymoshenko SWAP_32(ctt->ctt_name); 245a6425ab5SOleksandr Tymoshenko SWAP_16(ctt->ctt_info); 246a6425ab5SOleksandr Tymoshenko SWAP_16(ctt->ctt_size); 247a6425ab5SOleksandr Tymoshenko SWAP_32(ctt->ctt_lsizehi); 248a6425ab5SOleksandr Tymoshenko SWAP_32(ctt->ctt_lsizelo); 249a6425ab5SOleksandr Tymoshenko } 2501673e404SJohn Birrell ctf_buf_write(b, ctt, sizeof (*ctt)); 2511673e404SJohn Birrell } else { 2521673e404SJohn Birrell ctf_stype_t *cts = (ctf_stype_t *)ctt; 2531673e404SJohn Birrell 2541673e404SJohn Birrell cts->ctt_size = (ushort_t)size; 255a6425ab5SOleksandr Tymoshenko 256a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 257a6425ab5SOleksandr Tymoshenko SWAP_32(cts->ctt_name); 258a6425ab5SOleksandr Tymoshenko SWAP_16(cts->ctt_info); 259a6425ab5SOleksandr Tymoshenko SWAP_16(cts->ctt_size); 260a6425ab5SOleksandr Tymoshenko } 261a6425ab5SOleksandr Tymoshenko 2621673e404SJohn Birrell ctf_buf_write(b, cts, sizeof (*cts)); 2631673e404SJohn Birrell } 2641673e404SJohn Birrell } 2651673e404SJohn Birrell 2661673e404SJohn Birrell static void 2671673e404SJohn Birrell write_unsized_type_rec(ctf_buf_t *b, ctf_type_t *ctt) 2681673e404SJohn Birrell { 2691673e404SJohn Birrell ctf_stype_t *cts = (ctf_stype_t *)ctt; 2701673e404SJohn Birrell 271a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 272a6425ab5SOleksandr Tymoshenko SWAP_32(cts->ctt_name); 273a6425ab5SOleksandr Tymoshenko SWAP_16(cts->ctt_info); 274a6425ab5SOleksandr Tymoshenko SWAP_16(cts->ctt_size); 275a6425ab5SOleksandr Tymoshenko } 276a6425ab5SOleksandr Tymoshenko 2771673e404SJohn Birrell ctf_buf_write(b, cts, sizeof (*cts)); 2781673e404SJohn Birrell } 2791673e404SJohn Birrell 2801673e404SJohn Birrell static int 2814cc75139SJohn Birrell write_type(void *arg1, void *arg2) 2821673e404SJohn Birrell { 2834cc75139SJohn Birrell tdesc_t *tp = arg1; 2844cc75139SJohn Birrell ctf_buf_t *b = arg2; 2851673e404SJohn Birrell elist_t *ep; 2861673e404SJohn Birrell mlist_t *mp; 2871673e404SJohn Birrell intr_t *ip; 2881673e404SJohn Birrell 2891673e404SJohn Birrell size_t offset; 2901673e404SJohn Birrell uint_t encoding; 2911673e404SJohn Birrell uint_t data; 2921673e404SJohn Birrell int isroot = tp->t_flags & TDESC_F_ISROOT; 2931673e404SJohn Birrell int i; 2941673e404SJohn Birrell 2951673e404SJohn Birrell ctf_type_t ctt; 2961673e404SJohn Birrell ctf_array_t cta; 2971673e404SJohn Birrell ctf_member_t ctm; 2981673e404SJohn Birrell ctf_lmember_t ctlm; 2991673e404SJohn Birrell ctf_enum_t cte; 3001673e404SJohn Birrell ushort_t id; 3011673e404SJohn Birrell 3021673e404SJohn Birrell ctlm.ctlm_pad = 0; 3031673e404SJohn Birrell 3041673e404SJohn Birrell /* 3051673e404SJohn Birrell * There shouldn't be any holes in the type list (where a hole is 3061673e404SJohn Birrell * defined as two consecutive tdescs without consecutive ids), but 3071673e404SJohn Birrell * check for them just in case. If we do find holes, we need to make 3081673e404SJohn Birrell * fake entries to fill the holes, or we won't be able to reconstruct 3091673e404SJohn Birrell * the tree from the written data. 3101673e404SJohn Birrell */ 3111673e404SJohn Birrell if (++b->nptent < CTF_TYPE_TO_INDEX(tp->t_id)) { 3121673e404SJohn Birrell debug(2, "genctf: type hole from %d < x < %d\n", 3131673e404SJohn Birrell b->nptent - 1, CTF_TYPE_TO_INDEX(tp->t_id)); 3141673e404SJohn Birrell 3151673e404SJohn Birrell ctt.ctt_name = CTF_TYPE_NAME(CTF_STRTAB_0, 0); 3161673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(0, 0, 0); 3171673e404SJohn Birrell while (b->nptent < CTF_TYPE_TO_INDEX(tp->t_id)) { 3181673e404SJohn Birrell write_sized_type_rec(b, &ctt, 0); 3191673e404SJohn Birrell b->nptent++; 3201673e404SJohn Birrell } 3211673e404SJohn Birrell } 3221673e404SJohn Birrell 3231673e404SJohn Birrell offset = strtab_insert(&b->ctb_strtab, tp->t_name); 3241673e404SJohn Birrell ctt.ctt_name = CTF_TYPE_NAME(CTF_STRTAB_0, offset); 3251673e404SJohn Birrell 3261673e404SJohn Birrell switch (tp->t_type) { 3271673e404SJohn Birrell case INTRINSIC: 3281673e404SJohn Birrell ip = tp->t_intr; 3291673e404SJohn Birrell if (ip->intr_type == INTR_INT) 3301673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_INTEGER, 3311673e404SJohn Birrell isroot, 1); 3321673e404SJohn Birrell else 3331673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_FLOAT, isroot, 1); 3341673e404SJohn Birrell write_sized_type_rec(b, &ctt, tp->t_size); 3351673e404SJohn Birrell 3361673e404SJohn Birrell encoding = 0; 3371673e404SJohn Birrell 3381673e404SJohn Birrell if (ip->intr_type == INTR_INT) { 3391673e404SJohn Birrell if (ip->intr_signed) 3401673e404SJohn Birrell encoding |= CTF_INT_SIGNED; 3411673e404SJohn Birrell if (ip->intr_iformat == 'c') 3421673e404SJohn Birrell encoding |= CTF_INT_CHAR; 3431673e404SJohn Birrell else if (ip->intr_iformat == 'b') 3441673e404SJohn Birrell encoding |= CTF_INT_BOOL; 3451673e404SJohn Birrell else if (ip->intr_iformat == 'v') 3461673e404SJohn Birrell encoding |= CTF_INT_VARARGS; 3471673e404SJohn Birrell } else 3481673e404SJohn Birrell encoding = ip->intr_fformat; 3491673e404SJohn Birrell 3501673e404SJohn Birrell data = CTF_INT_DATA(encoding, ip->intr_offset, ip->intr_nbits); 351a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 352a6425ab5SOleksandr Tymoshenko SWAP_32(data); 353a6425ab5SOleksandr Tymoshenko } 3541673e404SJohn Birrell ctf_buf_write(b, &data, sizeof (data)); 3551673e404SJohn Birrell break; 3561673e404SJohn Birrell 3571673e404SJohn Birrell case POINTER: 3581673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_POINTER, isroot, 0); 3591673e404SJohn Birrell ctt.ctt_type = tp->t_tdesc->t_id; 3601673e404SJohn Birrell write_unsized_type_rec(b, &ctt); 3611673e404SJohn Birrell break; 3621673e404SJohn Birrell 3631673e404SJohn Birrell case ARRAY: 3641673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_ARRAY, isroot, 1); 3651673e404SJohn Birrell write_sized_type_rec(b, &ctt, tp->t_size); 3661673e404SJohn Birrell 3671673e404SJohn Birrell cta.cta_contents = tp->t_ardef->ad_contents->t_id; 3681673e404SJohn Birrell cta.cta_index = tp->t_ardef->ad_idxtype->t_id; 3691673e404SJohn Birrell cta.cta_nelems = tp->t_ardef->ad_nelems; 370a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 371a6425ab5SOleksandr Tymoshenko SWAP_16(cta.cta_contents); 372a6425ab5SOleksandr Tymoshenko SWAP_16(cta.cta_index); 373a6425ab5SOleksandr Tymoshenko SWAP_32(cta.cta_nelems); 374a6425ab5SOleksandr Tymoshenko } 3751673e404SJohn Birrell ctf_buf_write(b, &cta, sizeof (cta)); 3761673e404SJohn Birrell break; 3771673e404SJohn Birrell 3781673e404SJohn Birrell case STRUCT: 3791673e404SJohn Birrell case UNION: 3801673e404SJohn Birrell for (i = 0, mp = tp->t_members; mp != NULL; mp = mp->ml_next) 3811673e404SJohn Birrell i++; /* count up struct or union members */ 3821673e404SJohn Birrell 3831670a1c2SRui Paulo if (i > CTF_MAX_VLEN) { 3841670a1c2SRui Paulo terminate("sou %s has too many members: %d > %d\n", 3851670a1c2SRui Paulo tdesc_name(tp), i, CTF_MAX_VLEN); 3861670a1c2SRui Paulo } 3871670a1c2SRui Paulo 3881673e404SJohn Birrell if (tp->t_type == STRUCT) 3891673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_STRUCT, isroot, i); 3901673e404SJohn Birrell else 3911673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_UNION, isroot, i); 3921673e404SJohn Birrell 3931673e404SJohn Birrell write_sized_type_rec(b, &ctt, tp->t_size); 3941673e404SJohn Birrell 3951673e404SJohn Birrell if (tp->t_size < CTF_LSTRUCT_THRESH) { 3961673e404SJohn Birrell for (mp = tp->t_members; mp != NULL; mp = mp->ml_next) { 3971673e404SJohn Birrell offset = strtab_insert(&b->ctb_strtab, 3981673e404SJohn Birrell mp->ml_name); 3991673e404SJohn Birrell 4001673e404SJohn Birrell ctm.ctm_name = CTF_TYPE_NAME(CTF_STRTAB_0, 4011673e404SJohn Birrell offset); 4021673e404SJohn Birrell ctm.ctm_type = mp->ml_type->t_id; 4031673e404SJohn Birrell ctm.ctm_offset = mp->ml_offset; 404a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 405a6425ab5SOleksandr Tymoshenko SWAP_32(ctm.ctm_name); 406a6425ab5SOleksandr Tymoshenko SWAP_16(ctm.ctm_type); 407a6425ab5SOleksandr Tymoshenko SWAP_16(ctm.ctm_offset); 408a6425ab5SOleksandr Tymoshenko } 4091673e404SJohn Birrell ctf_buf_write(b, &ctm, sizeof (ctm)); 4101673e404SJohn Birrell } 4111673e404SJohn Birrell } else { 4121673e404SJohn Birrell for (mp = tp->t_members; mp != NULL; mp = mp->ml_next) { 4131673e404SJohn Birrell offset = strtab_insert(&b->ctb_strtab, 4141673e404SJohn Birrell mp->ml_name); 4151673e404SJohn Birrell 4161673e404SJohn Birrell ctlm.ctlm_name = CTF_TYPE_NAME(CTF_STRTAB_0, 4171673e404SJohn Birrell offset); 4181673e404SJohn Birrell ctlm.ctlm_type = mp->ml_type->t_id; 4191673e404SJohn Birrell ctlm.ctlm_offsethi = 4201673e404SJohn Birrell CTF_OFFSET_TO_LMEMHI(mp->ml_offset); 4211673e404SJohn Birrell ctlm.ctlm_offsetlo = 4221673e404SJohn Birrell CTF_OFFSET_TO_LMEMLO(mp->ml_offset); 423a6425ab5SOleksandr Tymoshenko 424a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 425a6425ab5SOleksandr Tymoshenko SWAP_32(ctlm.ctlm_name); 426a6425ab5SOleksandr Tymoshenko SWAP_16(ctlm.ctlm_type); 427a6425ab5SOleksandr Tymoshenko SWAP_32(ctlm.ctlm_offsethi); 428a6425ab5SOleksandr Tymoshenko SWAP_32(ctlm.ctlm_offsetlo); 429a6425ab5SOleksandr Tymoshenko } 430a6425ab5SOleksandr Tymoshenko 4311673e404SJohn Birrell ctf_buf_write(b, &ctlm, sizeof (ctlm)); 4321673e404SJohn Birrell } 4331673e404SJohn Birrell } 4341673e404SJohn Birrell break; 4351673e404SJohn Birrell 4361673e404SJohn Birrell case ENUM: 4371673e404SJohn Birrell for (i = 0, ep = tp->t_emem; ep != NULL; ep = ep->el_next) 4381673e404SJohn Birrell i++; /* count up enum members */ 4391673e404SJohn Birrell 44059879e52SAlexander Kabaev if (i > CTF_MAX_VLEN) { 44159879e52SAlexander Kabaev warning("enum %s has too many values: %d > %d\n", 44259879e52SAlexander Kabaev tdesc_name(tp), i, CTF_MAX_VLEN); 44359879e52SAlexander Kabaev i = CTF_MAX_VLEN; 44459879e52SAlexander Kabaev } 44559879e52SAlexander Kabaev 4461673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_ENUM, isroot, i); 4471673e404SJohn Birrell write_sized_type_rec(b, &ctt, tp->t_size); 4481673e404SJohn Birrell 44959879e52SAlexander Kabaev for (ep = tp->t_emem; ep != NULL && i > 0; ep = ep->el_next) { 4501673e404SJohn Birrell offset = strtab_insert(&b->ctb_strtab, ep->el_name); 4511673e404SJohn Birrell cte.cte_name = CTF_TYPE_NAME(CTF_STRTAB_0, offset); 4521673e404SJohn Birrell cte.cte_value = ep->el_number; 453a6425ab5SOleksandr Tymoshenko 454a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 455a6425ab5SOleksandr Tymoshenko SWAP_32(cte.cte_name); 456a6425ab5SOleksandr Tymoshenko SWAP_32(cte.cte_value); 457a6425ab5SOleksandr Tymoshenko } 458a6425ab5SOleksandr Tymoshenko 4591673e404SJohn Birrell ctf_buf_write(b, &cte, sizeof (cte)); 46059879e52SAlexander Kabaev i--; 4611673e404SJohn Birrell } 4621673e404SJohn Birrell break; 4631673e404SJohn Birrell 4641673e404SJohn Birrell case FORWARD: 4651673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_FORWARD, isroot, 0); 4661673e404SJohn Birrell ctt.ctt_type = 0; 4671673e404SJohn Birrell write_unsized_type_rec(b, &ctt); 4681673e404SJohn Birrell break; 4691673e404SJohn Birrell 4701673e404SJohn Birrell case TYPEDEF: 4711673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_TYPEDEF, isroot, 0); 4721673e404SJohn Birrell ctt.ctt_type = tp->t_tdesc->t_id; 4731673e404SJohn Birrell write_unsized_type_rec(b, &ctt); 4741673e404SJohn Birrell break; 4751673e404SJohn Birrell 4761673e404SJohn Birrell case VOLATILE: 4771673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_VOLATILE, isroot, 0); 4781673e404SJohn Birrell ctt.ctt_type = tp->t_tdesc->t_id; 4791673e404SJohn Birrell write_unsized_type_rec(b, &ctt); 4801673e404SJohn Birrell break; 4811673e404SJohn Birrell 4821673e404SJohn Birrell case CONST: 4831673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_CONST, isroot, 0); 4841673e404SJohn Birrell ctt.ctt_type = tp->t_tdesc->t_id; 4851673e404SJohn Birrell write_unsized_type_rec(b, &ctt); 4861673e404SJohn Birrell break; 4871673e404SJohn Birrell 4881673e404SJohn Birrell case FUNCTION: 4891670a1c2SRui Paulo i = tp->t_fndef->fn_nargs + tp->t_fndef->fn_vargs; 4901670a1c2SRui Paulo 4911670a1c2SRui Paulo if (i > CTF_MAX_VLEN) { 4921670a1c2SRui Paulo terminate("function %s has too many args: %d > %d\n", 493ad6fc754SMark Johnston tdesc_name(tp), i, CTF_MAX_VLEN); 4941670a1c2SRui Paulo } 4951670a1c2SRui Paulo 4961670a1c2SRui Paulo ctt.ctt_info = CTF_TYPE_INFO(CTF_K_FUNCTION, isroot, i); 4971673e404SJohn Birrell ctt.ctt_type = tp->t_fndef->fn_ret->t_id; 4981673e404SJohn Birrell write_unsized_type_rec(b, &ctt); 4991673e404SJohn Birrell 5004cc75139SJohn Birrell for (i = 0; i < (int) tp->t_fndef->fn_nargs; i++) { 5011673e404SJohn Birrell id = tp->t_fndef->fn_args[i]->t_id; 502a6425ab5SOleksandr Tymoshenko 503a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 504a6425ab5SOleksandr Tymoshenko SWAP_16(id); 505a6425ab5SOleksandr Tymoshenko } 506a6425ab5SOleksandr Tymoshenko 5071673e404SJohn Birrell ctf_buf_write(b, &id, sizeof (id)); 5081673e404SJohn Birrell } 5091673e404SJohn Birrell 5101673e404SJohn Birrell if (tp->t_fndef->fn_vargs) { 5111673e404SJohn Birrell id = 0; 5121673e404SJohn Birrell ctf_buf_write(b, &id, sizeof (id)); 5131673e404SJohn Birrell i++; 5141673e404SJohn Birrell } 5151673e404SJohn Birrell 5161673e404SJohn Birrell if (i & 1) { 5171673e404SJohn Birrell id = 0; 5181673e404SJohn Birrell ctf_buf_write(b, &id, sizeof (id)); 5191673e404SJohn Birrell } 5201673e404SJohn Birrell break; 5211673e404SJohn Birrell 5221673e404SJohn Birrell case RESTRICT: 5231673e404SJohn Birrell ctt.ctt_info = CTF_TYPE_INFO(CTF_K_RESTRICT, isroot, 0); 5241673e404SJohn Birrell ctt.ctt_type = tp->t_tdesc->t_id; 5251673e404SJohn Birrell write_unsized_type_rec(b, &ctt); 5261673e404SJohn Birrell break; 5271673e404SJohn Birrell 5281673e404SJohn Birrell default: 5291673e404SJohn Birrell warning("Can't write unknown type %d\n", tp->t_type); 5301673e404SJohn Birrell } 5311673e404SJohn Birrell 5321673e404SJohn Birrell debug(3, "Wrote type %d %s\n", tp->t_id, tdesc_name(tp)); 5331673e404SJohn Birrell 5341673e404SJohn Birrell return (1); 5351673e404SJohn Birrell } 5361673e404SJohn Birrell 5371673e404SJohn Birrell typedef struct resbuf { 5381673e404SJohn Birrell caddr_t rb_base; 5391673e404SJohn Birrell caddr_t rb_ptr; 5401673e404SJohn Birrell size_t rb_size; 5411673e404SJohn Birrell z_stream rb_zstr; 5421673e404SJohn Birrell } resbuf_t; 5431673e404SJohn Birrell 5441673e404SJohn Birrell static void 5451673e404SJohn Birrell rbzs_grow(resbuf_t *rb) 5461673e404SJohn Birrell { 5471673e404SJohn Birrell off_t ptroff = (caddr_t)rb->rb_zstr.next_out - rb->rb_base; 5481673e404SJohn Birrell 5491673e404SJohn Birrell rb->rb_size += RES_BUF_CHUNK_SIZE; 5501673e404SJohn Birrell rb->rb_base = xrealloc(rb->rb_base, rb->rb_size); 5511673e404SJohn Birrell rb->rb_ptr = rb->rb_base + ptroff; 5521673e404SJohn Birrell rb->rb_zstr.next_out = (Bytef *)(rb->rb_ptr); 5531673e404SJohn Birrell rb->rb_zstr.avail_out += RES_BUF_CHUNK_SIZE; 5541673e404SJohn Birrell } 5551673e404SJohn Birrell 5561673e404SJohn Birrell static void 5571673e404SJohn Birrell compress_start(resbuf_t *rb) 5581673e404SJohn Birrell { 5591673e404SJohn Birrell int rc; 5601673e404SJohn Birrell 5611673e404SJohn Birrell rb->rb_zstr.zalloc = (alloc_func)0; 5621673e404SJohn Birrell rb->rb_zstr.zfree = (free_func)0; 5631673e404SJohn Birrell rb->rb_zstr.opaque = (voidpf)0; 5641673e404SJohn Birrell 5651673e404SJohn Birrell if ((rc = deflateInit(&rb->rb_zstr, Z_BEST_COMPRESSION)) != Z_OK) 5661673e404SJohn Birrell parseterminate("zlib start failed: %s", zError(rc)); 5671673e404SJohn Birrell } 5681673e404SJohn Birrell 5691673e404SJohn Birrell static ssize_t 5704cc75139SJohn Birrell compress_buffer(void *buf, size_t n, void *data) 5711673e404SJohn Birrell { 5721673e404SJohn Birrell resbuf_t *rb = (resbuf_t *)data; 5731673e404SJohn Birrell int rc; 5741673e404SJohn Birrell 5751673e404SJohn Birrell rb->rb_zstr.next_out = (Bytef *)rb->rb_ptr; 5761673e404SJohn Birrell rb->rb_zstr.avail_out = rb->rb_size - (rb->rb_ptr - rb->rb_base); 5774cc75139SJohn Birrell rb->rb_zstr.next_in = buf; 5781673e404SJohn Birrell rb->rb_zstr.avail_in = n; 5791673e404SJohn Birrell 5801673e404SJohn Birrell while (rb->rb_zstr.avail_in) { 5811673e404SJohn Birrell if (rb->rb_zstr.avail_out == 0) 5821673e404SJohn Birrell rbzs_grow(rb); 5831673e404SJohn Birrell 5841673e404SJohn Birrell if ((rc = deflate(&rb->rb_zstr, Z_NO_FLUSH)) != Z_OK) 5851673e404SJohn Birrell parseterminate("zlib deflate failed: %s", zError(rc)); 5861673e404SJohn Birrell } 5871673e404SJohn Birrell rb->rb_ptr = (caddr_t)rb->rb_zstr.next_out; 5881673e404SJohn Birrell 5891673e404SJohn Birrell return (n); 5901673e404SJohn Birrell } 5911673e404SJohn Birrell 5921673e404SJohn Birrell static void 5931673e404SJohn Birrell compress_flush(resbuf_t *rb, int type) 5941673e404SJohn Birrell { 5951673e404SJohn Birrell int rc; 5961673e404SJohn Birrell 5971673e404SJohn Birrell for (;;) { 5981673e404SJohn Birrell if (rb->rb_zstr.avail_out == 0) 5991673e404SJohn Birrell rbzs_grow(rb); 6001673e404SJohn Birrell 6011673e404SJohn Birrell rc = deflate(&rb->rb_zstr, type); 6021673e404SJohn Birrell if ((type == Z_FULL_FLUSH && rc == Z_BUF_ERROR) || 6031673e404SJohn Birrell (type == Z_FINISH && rc == Z_STREAM_END)) 6041673e404SJohn Birrell break; 6051673e404SJohn Birrell else if (rc != Z_OK) 6061673e404SJohn Birrell parseterminate("zlib finish failed: %s", zError(rc)); 6071673e404SJohn Birrell } 6081673e404SJohn Birrell rb->rb_ptr = (caddr_t)rb->rb_zstr.next_out; 6091673e404SJohn Birrell } 6101673e404SJohn Birrell 6111673e404SJohn Birrell static void 6121673e404SJohn Birrell compress_end(resbuf_t *rb) 6131673e404SJohn Birrell { 6141673e404SJohn Birrell int rc; 6151673e404SJohn Birrell 6161673e404SJohn Birrell compress_flush(rb, Z_FINISH); 6171673e404SJohn Birrell 6181673e404SJohn Birrell if ((rc = deflateEnd(&rb->rb_zstr)) != Z_OK) 6191673e404SJohn Birrell parseterminate("zlib end failed: %s", zError(rc)); 6201673e404SJohn Birrell } 6211673e404SJohn Birrell 6221673e404SJohn Birrell /* 6231673e404SJohn Birrell * Pad the buffer to a power-of-2 boundary 6241673e404SJohn Birrell */ 6251673e404SJohn Birrell static void 6261673e404SJohn Birrell pad_buffer(ctf_buf_t *buf, int align) 6271673e404SJohn Birrell { 6281673e404SJohn Birrell uint_t cur = ctf_buf_cur(buf); 6291673e404SJohn Birrell ssize_t topad = (align - (cur % align)) % align; 6301673e404SJohn Birrell static const char pad[8] = { 0 }; 6311673e404SJohn Birrell 6321673e404SJohn Birrell while (topad > 0) { 6331673e404SJohn Birrell ctf_buf_write(buf, pad, (topad > 8 ? 8 : topad)); 6341673e404SJohn Birrell topad -= 8; 6351673e404SJohn Birrell } 6361673e404SJohn Birrell } 6371673e404SJohn Birrell 6381673e404SJohn Birrell static ssize_t 6394cc75139SJohn Birrell bcopy_data(void *buf, size_t n, void *data) 6401673e404SJohn Birrell { 6411673e404SJohn Birrell caddr_t *posp = (caddr_t *)data; 6421673e404SJohn Birrell bcopy(buf, *posp, n); 6431673e404SJohn Birrell *posp += n; 6441673e404SJohn Birrell return (n); 6451673e404SJohn Birrell } 6461673e404SJohn Birrell 6471673e404SJohn Birrell static caddr_t 6481673e404SJohn Birrell write_buffer(ctf_header_t *h, ctf_buf_t *buf, size_t *resszp) 6491673e404SJohn Birrell { 6501673e404SJohn Birrell caddr_t outbuf; 6511673e404SJohn Birrell caddr_t bufpos; 6521673e404SJohn Birrell 6531673e404SJohn Birrell outbuf = xmalloc(sizeof (ctf_header_t) + (buf->ctb_ptr - buf->ctb_base) 6541673e404SJohn Birrell + buf->ctb_strtab.str_size); 6551673e404SJohn Birrell 6561673e404SJohn Birrell bufpos = outbuf; 6571673e404SJohn Birrell (void) bcopy_data(h, sizeof (ctf_header_t), &bufpos); 6581673e404SJohn Birrell (void) bcopy_data(buf->ctb_base, buf->ctb_ptr - buf->ctb_base, 6591673e404SJohn Birrell &bufpos); 6601673e404SJohn Birrell (void) strtab_write(&buf->ctb_strtab, bcopy_data, &bufpos); 6611673e404SJohn Birrell *resszp = bufpos - outbuf; 6621673e404SJohn Birrell return (outbuf); 6631673e404SJohn Birrell } 6641673e404SJohn Birrell 6651673e404SJohn Birrell /* 6661673e404SJohn Birrell * Create the compression buffer, and fill it with the CTF and string 6671673e404SJohn Birrell * table data. We flush the compression state between the two so the 6681673e404SJohn Birrell * dictionary used for the string tables won't be polluted with values 6691673e404SJohn Birrell * that made sense for the CTF data. 6701673e404SJohn Birrell */ 6711673e404SJohn Birrell static caddr_t 6721673e404SJohn Birrell write_compressed_buffer(ctf_header_t *h, ctf_buf_t *buf, size_t *resszp) 6731673e404SJohn Birrell { 6741673e404SJohn Birrell resbuf_t resbuf; 6751673e404SJohn Birrell resbuf.rb_size = RES_BUF_CHUNK_SIZE; 6761673e404SJohn Birrell resbuf.rb_base = xmalloc(resbuf.rb_size); 6771673e404SJohn Birrell bcopy(h, resbuf.rb_base, sizeof (ctf_header_t)); 6781673e404SJohn Birrell resbuf.rb_ptr = resbuf.rb_base + sizeof (ctf_header_t); 6791673e404SJohn Birrell 6801673e404SJohn Birrell compress_start(&resbuf); 6811673e404SJohn Birrell (void) compress_buffer(buf->ctb_base, buf->ctb_ptr - buf->ctb_base, 6821673e404SJohn Birrell &resbuf); 6831673e404SJohn Birrell compress_flush(&resbuf, Z_FULL_FLUSH); 6841673e404SJohn Birrell (void) strtab_write(&buf->ctb_strtab, compress_buffer, &resbuf); 6851673e404SJohn Birrell compress_end(&resbuf); 6861673e404SJohn Birrell 6871673e404SJohn Birrell *resszp = (resbuf.rb_ptr - resbuf.rb_base); 6881673e404SJohn Birrell return (resbuf.rb_base); 6891673e404SJohn Birrell } 6901673e404SJohn Birrell 6911673e404SJohn Birrell caddr_t 6921673e404SJohn Birrell ctf_gen(iiburst_t *iiburst, size_t *resszp, int do_compress) 6931673e404SJohn Birrell { 6941673e404SJohn Birrell ctf_buf_t *buf = ctf_buf_new(); 6951673e404SJohn Birrell ctf_header_t h; 6961673e404SJohn Birrell caddr_t outbuf; 6971673e404SJohn Birrell 6981673e404SJohn Birrell int i; 6991673e404SJohn Birrell 700a6425ab5SOleksandr Tymoshenko target_requires_swap = do_compress & CTF_SWAP_BYTES; 701a6425ab5SOleksandr Tymoshenko do_compress &= ~CTF_SWAP_BYTES; 702a6425ab5SOleksandr Tymoshenko 7031673e404SJohn Birrell /* 7041673e404SJohn Birrell * Prepare the header, and create the CTF output buffers. The data 7051673e404SJohn Birrell * object section and function section are both lists of 2-byte 7061673e404SJohn Birrell * integers; we pad these out to the next 4-byte boundary if needed. 7071673e404SJohn Birrell */ 7081673e404SJohn Birrell h.cth_magic = CTF_MAGIC; 7091673e404SJohn Birrell h.cth_version = CTF_VERSION; 7101673e404SJohn Birrell h.cth_flags = do_compress ? CTF_F_COMPRESS : 0; 7111673e404SJohn Birrell h.cth_parlabel = strtab_insert(&buf->ctb_strtab, 7121673e404SJohn Birrell iiburst->iib_td->td_parlabel); 7131673e404SJohn Birrell h.cth_parname = strtab_insert(&buf->ctb_strtab, 7141673e404SJohn Birrell iiburst->iib_td->td_parname); 7151673e404SJohn Birrell 7161673e404SJohn Birrell h.cth_lbloff = 0; 7174cc75139SJohn Birrell (void) list_iter(iiburst->iib_td->td_labels, write_label, 7181673e404SJohn Birrell buf); 7191673e404SJohn Birrell 7201673e404SJohn Birrell pad_buffer(buf, 2); 7211673e404SJohn Birrell h.cth_objtoff = ctf_buf_cur(buf); 7221673e404SJohn Birrell for (i = 0; i < iiburst->iib_nobjts; i++) 7231673e404SJohn Birrell write_objects(iiburst->iib_objts[i], buf); 7241673e404SJohn Birrell 7251673e404SJohn Birrell pad_buffer(buf, 2); 7261673e404SJohn Birrell h.cth_funcoff = ctf_buf_cur(buf); 7271673e404SJohn Birrell for (i = 0; i < iiburst->iib_nfuncs; i++) 7281673e404SJohn Birrell write_functions(iiburst->iib_funcs[i], buf); 7291673e404SJohn Birrell 7301673e404SJohn Birrell pad_buffer(buf, 4); 7311673e404SJohn Birrell h.cth_typeoff = ctf_buf_cur(buf); 7324cc75139SJohn Birrell (void) list_iter(iiburst->iib_types, write_type, buf); 7331673e404SJohn Birrell 7341673e404SJohn Birrell debug(2, "CTF wrote %d types\n", list_count(iiburst->iib_types)); 7351673e404SJohn Birrell 7361673e404SJohn Birrell h.cth_stroff = ctf_buf_cur(buf); 7371673e404SJohn Birrell h.cth_strlen = strtab_size(&buf->ctb_strtab); 7381673e404SJohn Birrell 739a6425ab5SOleksandr Tymoshenko if (target_requires_swap) { 740a6425ab5SOleksandr Tymoshenko SWAP_16(h.cth_preamble.ctp_magic); 741a6425ab5SOleksandr Tymoshenko SWAP_32(h.cth_parlabel); 742a6425ab5SOleksandr Tymoshenko SWAP_32(h.cth_parname); 743a6425ab5SOleksandr Tymoshenko SWAP_32(h.cth_lbloff); 744a6425ab5SOleksandr Tymoshenko SWAP_32(h.cth_objtoff); 745a6425ab5SOleksandr Tymoshenko SWAP_32(h.cth_funcoff); 746a6425ab5SOleksandr Tymoshenko SWAP_32(h.cth_typeoff); 747a6425ab5SOleksandr Tymoshenko SWAP_32(h.cth_stroff); 748a6425ab5SOleksandr Tymoshenko SWAP_32(h.cth_strlen); 749a6425ab5SOleksandr Tymoshenko } 750a6425ab5SOleksandr Tymoshenko 7511673e404SJohn Birrell /* 7521673e404SJohn Birrell * We only do compression for ctfmerge, as ctfconvert is only 7531673e404SJohn Birrell * supposed to be used on intermediary build objects. This is 7541673e404SJohn Birrell * significantly faster. 7551673e404SJohn Birrell */ 7561673e404SJohn Birrell if (do_compress) 7571673e404SJohn Birrell outbuf = write_compressed_buffer(&h, buf, resszp); 7581673e404SJohn Birrell else 7591673e404SJohn Birrell outbuf = write_buffer(&h, buf, resszp); 7601673e404SJohn Birrell 7611673e404SJohn Birrell ctf_buf_free(buf); 7621673e404SJohn Birrell return (outbuf); 7631673e404SJohn Birrell } 7641673e404SJohn Birrell 7654cc75139SJohn Birrell static void 7661673e404SJohn Birrell get_ctt_size(ctf_type_t *ctt, size_t *sizep, size_t *incrementp) 7671673e404SJohn Birrell { 7681673e404SJohn Birrell if (ctt->ctt_size == CTF_LSIZE_SENT) { 7691673e404SJohn Birrell *sizep = (size_t)CTF_TYPE_LSIZE(ctt); 7701673e404SJohn Birrell *incrementp = sizeof (ctf_type_t); 7711673e404SJohn Birrell } else { 7721673e404SJohn Birrell *sizep = ctt->ctt_size; 7731673e404SJohn Birrell *incrementp = sizeof (ctf_stype_t); 7741673e404SJohn Birrell } 7751673e404SJohn Birrell } 7761673e404SJohn Birrell 7771673e404SJohn Birrell static int 7781673e404SJohn Birrell count_types(ctf_header_t *h, caddr_t data) 7791673e404SJohn Birrell { 7801673e404SJohn Birrell caddr_t dptr = data + h->cth_typeoff; 7811673e404SJohn Birrell int count = 0; 7821673e404SJohn Birrell 7831673e404SJohn Birrell dptr = data + h->cth_typeoff; 7841673e404SJohn Birrell while (dptr < data + h->cth_stroff) { 7854cc75139SJohn Birrell void *v = (void *) dptr; 7864cc75139SJohn Birrell ctf_type_t *ctt = v; 7871673e404SJohn Birrell size_t vlen = CTF_INFO_VLEN(ctt->ctt_info); 7881673e404SJohn Birrell size_t size, increment; 7891673e404SJohn Birrell 7901673e404SJohn Birrell get_ctt_size(ctt, &size, &increment); 7911673e404SJohn Birrell 7921673e404SJohn Birrell switch (CTF_INFO_KIND(ctt->ctt_info)) { 7931673e404SJohn Birrell case CTF_K_INTEGER: 7941673e404SJohn Birrell case CTF_K_FLOAT: 7951673e404SJohn Birrell dptr += 4; 7961673e404SJohn Birrell break; 7971673e404SJohn Birrell case CTF_K_POINTER: 7981673e404SJohn Birrell case CTF_K_FORWARD: 7991673e404SJohn Birrell case CTF_K_TYPEDEF: 8001673e404SJohn Birrell case CTF_K_VOLATILE: 8011673e404SJohn Birrell case CTF_K_CONST: 8021673e404SJohn Birrell case CTF_K_RESTRICT: 8031673e404SJohn Birrell case CTF_K_FUNCTION: 8041673e404SJohn Birrell dptr += sizeof (ushort_t) * (vlen + (vlen & 1)); 8051673e404SJohn Birrell break; 8061673e404SJohn Birrell case CTF_K_ARRAY: 8071673e404SJohn Birrell dptr += sizeof (ctf_array_t); 8081673e404SJohn Birrell break; 8091673e404SJohn Birrell case CTF_K_STRUCT: 8101673e404SJohn Birrell case CTF_K_UNION: 8111673e404SJohn Birrell if (size < CTF_LSTRUCT_THRESH) 8121673e404SJohn Birrell dptr += sizeof (ctf_member_t) * vlen; 8131673e404SJohn Birrell else 8141673e404SJohn Birrell dptr += sizeof (ctf_lmember_t) * vlen; 8151673e404SJohn Birrell break; 8161673e404SJohn Birrell case CTF_K_ENUM: 8171673e404SJohn Birrell dptr += sizeof (ctf_enum_t) * vlen; 8181673e404SJohn Birrell break; 8191673e404SJohn Birrell case CTF_K_UNKNOWN: 8201673e404SJohn Birrell break; 8211673e404SJohn Birrell default: 8221673e404SJohn Birrell parseterminate("Unknown CTF type %d (#%d) at %#x", 8231673e404SJohn Birrell CTF_INFO_KIND(ctt->ctt_info), count, dptr - data); 8241673e404SJohn Birrell } 8251673e404SJohn Birrell 8261673e404SJohn Birrell dptr += increment; 8271673e404SJohn Birrell count++; 8281673e404SJohn Birrell } 8291673e404SJohn Birrell 8301673e404SJohn Birrell debug(3, "CTF read %d types\n", count); 8311673e404SJohn Birrell 8321673e404SJohn Birrell return (count); 8331673e404SJohn Birrell } 8341673e404SJohn Birrell 8351673e404SJohn Birrell /* 8361673e404SJohn Birrell * Resurrect the labels stored in the CTF data, returning the index associated 8371673e404SJohn Birrell * with a label provided by the caller. There are several cases, outlined 8381673e404SJohn Birrell * below. Note that, given two labels, the one associated with the lesser type 8391673e404SJohn Birrell * index is considered to be older than the other. 8401673e404SJohn Birrell * 8411673e404SJohn Birrell * 1. matchlbl == NULL - return the index of the most recent label. 8421673e404SJohn Birrell * 2. matchlbl == "BASE" - return the index of the oldest label. 8431673e404SJohn Birrell * 3. matchlbl != NULL, but doesn't match any labels in the section - warn 8441673e404SJohn Birrell * the user, and proceed as if matchlbl == "BASE" (for safety). 8451673e404SJohn Birrell * 4. matchlbl != NULL, and matches one of the labels in the section - return 8461673e404SJohn Birrell * the type index associated with the label. 8471673e404SJohn Birrell */ 8481673e404SJohn Birrell static int 8491673e404SJohn Birrell resurrect_labels(ctf_header_t *h, tdata_t *td, caddr_t ctfdata, char *matchlbl) 8501673e404SJohn Birrell { 8511673e404SJohn Birrell caddr_t buf = ctfdata + h->cth_lbloff; 8521673e404SJohn Birrell caddr_t sbuf = ctfdata + h->cth_stroff; 8531673e404SJohn Birrell size_t bufsz = h->cth_objtoff - h->cth_lbloff; 8541673e404SJohn Birrell int lastidx = 0, baseidx = -1; 8554cc75139SJohn Birrell char *baselabel = NULL; 8561673e404SJohn Birrell ctf_lblent_t *ctl; 8574cc75139SJohn Birrell void *v = (void *) buf; 8581673e404SJohn Birrell 8594cc75139SJohn Birrell for (ctl = v; (caddr_t)ctl < buf + bufsz; ctl++) { 8601673e404SJohn Birrell char *label = sbuf + ctl->ctl_label; 8611673e404SJohn Birrell 8621673e404SJohn Birrell lastidx = ctl->ctl_typeidx; 8631673e404SJohn Birrell 8641673e404SJohn Birrell debug(3, "Resurrected label %s type idx %d\n", label, lastidx); 8651673e404SJohn Birrell 8661673e404SJohn Birrell tdata_label_add(td, label, lastidx); 8671673e404SJohn Birrell 8681673e404SJohn Birrell if (baseidx == -1) { 8691673e404SJohn Birrell baseidx = lastidx; 8701673e404SJohn Birrell baselabel = label; 8711673e404SJohn Birrell if (matchlbl != NULL && streq(matchlbl, "BASE")) 8721673e404SJohn Birrell return (lastidx); 8731673e404SJohn Birrell } 8741673e404SJohn Birrell 8751673e404SJohn Birrell if (matchlbl != NULL && streq(label, matchlbl)) 8761673e404SJohn Birrell return (lastidx); 8771673e404SJohn Birrell } 8781673e404SJohn Birrell 8791673e404SJohn Birrell if (matchlbl != NULL) { 8801673e404SJohn Birrell /* User provided a label that didn't match */ 8811673e404SJohn Birrell warning("%s: Cannot find label `%s' - using base (%s)\n", 8821673e404SJohn Birrell curfile, matchlbl, (baselabel ? baselabel : "NONE")); 8831673e404SJohn Birrell 8841673e404SJohn Birrell tdata_label_free(td); 8851673e404SJohn Birrell tdata_label_add(td, baselabel, baseidx); 8861673e404SJohn Birrell 8871673e404SJohn Birrell return (baseidx); 8881673e404SJohn Birrell } 8891673e404SJohn Birrell 8901673e404SJohn Birrell return (lastidx); 8911673e404SJohn Birrell } 8921673e404SJohn Birrell 8931673e404SJohn Birrell static void 8941673e404SJohn Birrell resurrect_objects(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize, 8951673e404SJohn Birrell caddr_t ctfdata, symit_data_t *si) 8961673e404SJohn Birrell { 8971673e404SJohn Birrell caddr_t buf = ctfdata + h->cth_objtoff; 8981673e404SJohn Birrell size_t bufsz = h->cth_funcoff - h->cth_objtoff; 8991673e404SJohn Birrell caddr_t dptr; 9001673e404SJohn Birrell 9011673e404SJohn Birrell symit_reset(si); 9021673e404SJohn Birrell for (dptr = buf; dptr < buf + bufsz; dptr += 2) { 9034cc75139SJohn Birrell void *v = (void *) dptr; 9044cc75139SJohn Birrell ushort_t id = *((ushort_t *)v); 9051673e404SJohn Birrell iidesc_t *ii; 9061673e404SJohn Birrell GElf_Sym *sym; 9071673e404SJohn Birrell 9081673e404SJohn Birrell if (!(sym = symit_next(si, STT_OBJECT)) && id != 0) { 9091673e404SJohn Birrell parseterminate( 9101673e404SJohn Birrell "Unexpected end of object symbols at %x of %x", 9111673e404SJohn Birrell dptr - buf, bufsz); 9121673e404SJohn Birrell } 9131673e404SJohn Birrell 9141673e404SJohn Birrell if (id == 0) { 9151673e404SJohn Birrell debug(3, "Skipping null object\n"); 9161673e404SJohn Birrell continue; 9171673e404SJohn Birrell } else if (id >= tdsize) { 9181673e404SJohn Birrell parseterminate("Reference to invalid type %d", id); 9191673e404SJohn Birrell } 9201673e404SJohn Birrell 9211673e404SJohn Birrell ii = iidesc_new(symit_name(si)); 9221673e404SJohn Birrell ii->ii_dtype = tdarr[id]; 9231673e404SJohn Birrell if (GELF_ST_BIND(sym->st_info) == STB_LOCAL) { 9241673e404SJohn Birrell ii->ii_type = II_SVAR; 9251673e404SJohn Birrell ii->ii_owner = xstrdup(symit_curfile(si)); 9261673e404SJohn Birrell } else 9271673e404SJohn Birrell ii->ii_type = II_GVAR; 9281673e404SJohn Birrell hash_add(td->td_iihash, ii); 9291673e404SJohn Birrell 9301673e404SJohn Birrell debug(3, "Resurrected %s object %s (%d) from %s\n", 9311673e404SJohn Birrell (ii->ii_type == II_GVAR ? "global" : "static"), 9321673e404SJohn Birrell ii->ii_name, id, (ii->ii_owner ? ii->ii_owner : "(none)")); 9331673e404SJohn Birrell } 9341673e404SJohn Birrell } 9351673e404SJohn Birrell 9361673e404SJohn Birrell static void 9371673e404SJohn Birrell resurrect_functions(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize, 9381673e404SJohn Birrell caddr_t ctfdata, symit_data_t *si) 9391673e404SJohn Birrell { 9401673e404SJohn Birrell caddr_t buf = ctfdata + h->cth_funcoff; 9411673e404SJohn Birrell size_t bufsz = h->cth_typeoff - h->cth_funcoff; 9421673e404SJohn Birrell caddr_t dptr = buf; 9431673e404SJohn Birrell iidesc_t *ii; 9441673e404SJohn Birrell ushort_t info; 9451673e404SJohn Birrell ushort_t retid; 9461673e404SJohn Birrell GElf_Sym *sym; 9471673e404SJohn Birrell int i; 9481673e404SJohn Birrell 9491673e404SJohn Birrell symit_reset(si); 9501673e404SJohn Birrell while (dptr < buf + bufsz) { 9514cc75139SJohn Birrell void *v = (void *) dptr; 9524cc75139SJohn Birrell info = *((ushort_t *)v); 9531673e404SJohn Birrell dptr += 2; 9541673e404SJohn Birrell 9551673e404SJohn Birrell if (!(sym = symit_next(si, STT_FUNC)) && info != 0) 9561673e404SJohn Birrell parseterminate("Unexpected end of function symbols"); 9571673e404SJohn Birrell 9581673e404SJohn Birrell if (info == 0) { 9591673e404SJohn Birrell debug(3, "Skipping null function (%s)\n", 9601673e404SJohn Birrell symit_name(si)); 9611673e404SJohn Birrell continue; 9621673e404SJohn Birrell } 9631673e404SJohn Birrell 9644cc75139SJohn Birrell v = (void *) dptr; 9654cc75139SJohn Birrell retid = *((ushort_t *)v); 9661673e404SJohn Birrell dptr += 2; 9671673e404SJohn Birrell 9681673e404SJohn Birrell if (retid >= tdsize) 9691673e404SJohn Birrell parseterminate("Reference to invalid type %d", retid); 9701673e404SJohn Birrell 9711673e404SJohn Birrell ii = iidesc_new(symit_name(si)); 9721673e404SJohn Birrell ii->ii_dtype = tdarr[retid]; 9731673e404SJohn Birrell if (GELF_ST_BIND(sym->st_info) == STB_LOCAL) { 9741673e404SJohn Birrell ii->ii_type = II_SFUN; 9751673e404SJohn Birrell ii->ii_owner = xstrdup(symit_curfile(si)); 9761673e404SJohn Birrell } else 9771673e404SJohn Birrell ii->ii_type = II_GFUN; 9781673e404SJohn Birrell ii->ii_nargs = CTF_INFO_VLEN(info); 9791673e404SJohn Birrell if (ii->ii_nargs) 9801673e404SJohn Birrell ii->ii_args = 9811673e404SJohn Birrell xmalloc(sizeof (tdesc_t *) * ii->ii_nargs); 9821673e404SJohn Birrell 9831673e404SJohn Birrell for (i = 0; i < ii->ii_nargs; i++, dptr += 2) { 9844cc75139SJohn Birrell v = (void *) dptr; 9854cc75139SJohn Birrell ushort_t id = *((ushort_t *)v); 9861673e404SJohn Birrell if (id >= tdsize) 9871673e404SJohn Birrell parseterminate("Reference to invalid type %d", 9881673e404SJohn Birrell id); 9891673e404SJohn Birrell ii->ii_args[i] = tdarr[id]; 9901673e404SJohn Birrell } 9911673e404SJohn Birrell 9921673e404SJohn Birrell if (ii->ii_nargs && ii->ii_args[ii->ii_nargs - 1] == NULL) { 9931673e404SJohn Birrell ii->ii_nargs--; 9941673e404SJohn Birrell ii->ii_vargs = 1; 9951673e404SJohn Birrell } 9961673e404SJohn Birrell 9971673e404SJohn Birrell hash_add(td->td_iihash, ii); 9981673e404SJohn Birrell 9991673e404SJohn Birrell debug(3, "Resurrected %s function %s (%d, %d args)\n", 10001673e404SJohn Birrell (ii->ii_type == II_GFUN ? "global" : "static"), 10011673e404SJohn Birrell ii->ii_name, retid, ii->ii_nargs); 10021673e404SJohn Birrell } 10031673e404SJohn Birrell } 10041673e404SJohn Birrell 10051673e404SJohn Birrell static void 10061673e404SJohn Birrell resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize, 10071673e404SJohn Birrell caddr_t ctfdata, int maxid) 10081673e404SJohn Birrell { 10091673e404SJohn Birrell caddr_t buf = ctfdata + h->cth_typeoff; 10101673e404SJohn Birrell size_t bufsz = h->cth_stroff - h->cth_typeoff; 10111673e404SJohn Birrell caddr_t sbuf = ctfdata + h->cth_stroff; 10121673e404SJohn Birrell caddr_t dptr = buf; 10131673e404SJohn Birrell tdesc_t *tdp; 10141673e404SJohn Birrell uint_t data; 10151673e404SJohn Birrell uint_t encoding; 10161673e404SJohn Birrell size_t size, increment; 10171673e404SJohn Birrell int tcnt; 10181673e404SJohn Birrell int iicnt = 0; 10191673e404SJohn Birrell tid_t tid, argid; 10201673e404SJohn Birrell int kind, vlen; 10211673e404SJohn Birrell int i; 10221673e404SJohn Birrell 10231673e404SJohn Birrell elist_t **epp; 10241673e404SJohn Birrell mlist_t **mpp; 10251673e404SJohn Birrell intr_t *ip; 10261673e404SJohn Birrell 10271673e404SJohn Birrell ctf_type_t *ctt; 10281673e404SJohn Birrell ctf_array_t *cta; 10291673e404SJohn Birrell ctf_enum_t *cte; 10301673e404SJohn Birrell 10311673e404SJohn Birrell /* 10321673e404SJohn Birrell * A maxid of zero indicates a request to resurrect all types, so reset 10331673e404SJohn Birrell * maxid to the maximum type id. 10341673e404SJohn Birrell */ 10351673e404SJohn Birrell if (maxid == 0) 10361673e404SJohn Birrell maxid = CTF_MAX_TYPE; 10371673e404SJohn Birrell 10381673e404SJohn Birrell for (dptr = buf, tcnt = 0, tid = 1; dptr < buf + bufsz; tcnt++, tid++) { 10391673e404SJohn Birrell if (tid > maxid) 10401673e404SJohn Birrell break; 10411673e404SJohn Birrell 10421673e404SJohn Birrell if (tid >= tdsize) 10431673e404SJohn Birrell parseterminate("Reference to invalid type %d", tid); 10441673e404SJohn Birrell 10454cc75139SJohn Birrell void *v = (void *) dptr; 10464cc75139SJohn Birrell ctt = v; 10471673e404SJohn Birrell 10481673e404SJohn Birrell get_ctt_size(ctt, &size, &increment); 10491673e404SJohn Birrell dptr += increment; 10501673e404SJohn Birrell 10511673e404SJohn Birrell tdp = tdarr[tid]; 10521673e404SJohn Birrell 10531673e404SJohn Birrell if (CTF_NAME_STID(ctt->ctt_name) != CTF_STRTAB_0) 10541673e404SJohn Birrell parseterminate( 10551673e404SJohn Birrell "Unable to cope with non-zero strtab id"); 10561673e404SJohn Birrell if (CTF_NAME_OFFSET(ctt->ctt_name) != 0) { 10571673e404SJohn Birrell tdp->t_name = 10581673e404SJohn Birrell xstrdup(sbuf + CTF_NAME_OFFSET(ctt->ctt_name)); 10591673e404SJohn Birrell } else 10601673e404SJohn Birrell tdp->t_name = NULL; 10611673e404SJohn Birrell 10621673e404SJohn Birrell kind = CTF_INFO_KIND(ctt->ctt_info); 10631673e404SJohn Birrell vlen = CTF_INFO_VLEN(ctt->ctt_info); 10641673e404SJohn Birrell 10651673e404SJohn Birrell switch (kind) { 10661673e404SJohn Birrell case CTF_K_INTEGER: 10671673e404SJohn Birrell tdp->t_type = INTRINSIC; 10681673e404SJohn Birrell tdp->t_size = size; 10691673e404SJohn Birrell 10704cc75139SJohn Birrell v = (void *) dptr; 10714cc75139SJohn Birrell data = *((uint_t *)v); 10721673e404SJohn Birrell dptr += sizeof (uint_t); 10731673e404SJohn Birrell encoding = CTF_INT_ENCODING(data); 10741673e404SJohn Birrell 10751673e404SJohn Birrell ip = xmalloc(sizeof (intr_t)); 10761673e404SJohn Birrell ip->intr_type = INTR_INT; 10771673e404SJohn Birrell ip->intr_signed = (encoding & CTF_INT_SIGNED) ? 1 : 0; 10781673e404SJohn Birrell 10791673e404SJohn Birrell if (encoding & CTF_INT_CHAR) 10801673e404SJohn Birrell ip->intr_iformat = 'c'; 10811673e404SJohn Birrell else if (encoding & CTF_INT_BOOL) 10821673e404SJohn Birrell ip->intr_iformat = 'b'; 10831673e404SJohn Birrell else if (encoding & CTF_INT_VARARGS) 10841673e404SJohn Birrell ip->intr_iformat = 'v'; 10851673e404SJohn Birrell else 10861673e404SJohn Birrell ip->intr_iformat = '\0'; 10871673e404SJohn Birrell 10881673e404SJohn Birrell ip->intr_offset = CTF_INT_OFFSET(data); 10891673e404SJohn Birrell ip->intr_nbits = CTF_INT_BITS(data); 10901673e404SJohn Birrell tdp->t_intr = ip; 10911673e404SJohn Birrell break; 10921673e404SJohn Birrell 10931673e404SJohn Birrell case CTF_K_FLOAT: 10941673e404SJohn Birrell tdp->t_type = INTRINSIC; 10951673e404SJohn Birrell tdp->t_size = size; 10961673e404SJohn Birrell 10974cc75139SJohn Birrell v = (void *) dptr; 10984cc75139SJohn Birrell data = *((uint_t *)v); 10991673e404SJohn Birrell dptr += sizeof (uint_t); 11001673e404SJohn Birrell 11011673e404SJohn Birrell ip = xcalloc(sizeof (intr_t)); 11021673e404SJohn Birrell ip->intr_type = INTR_REAL; 11031673e404SJohn Birrell ip->intr_fformat = CTF_FP_ENCODING(data); 11041673e404SJohn Birrell ip->intr_offset = CTF_FP_OFFSET(data); 11051673e404SJohn Birrell ip->intr_nbits = CTF_FP_BITS(data); 11061673e404SJohn Birrell tdp->t_intr = ip; 11071673e404SJohn Birrell break; 11081673e404SJohn Birrell 11091673e404SJohn Birrell case CTF_K_POINTER: 11101673e404SJohn Birrell tdp->t_type = POINTER; 11111673e404SJohn Birrell tdp->t_tdesc = tdarr[ctt->ctt_type]; 11121673e404SJohn Birrell break; 11131673e404SJohn Birrell 11141673e404SJohn Birrell case CTF_K_ARRAY: 11151673e404SJohn Birrell tdp->t_type = ARRAY; 11161673e404SJohn Birrell tdp->t_size = size; 11171673e404SJohn Birrell 11184cc75139SJohn Birrell v = (void *) dptr; 11194cc75139SJohn Birrell cta = v; 11201673e404SJohn Birrell dptr += sizeof (ctf_array_t); 11211673e404SJohn Birrell 11221673e404SJohn Birrell tdp->t_ardef = xmalloc(sizeof (ardef_t)); 11231673e404SJohn Birrell tdp->t_ardef->ad_contents = tdarr[cta->cta_contents]; 11241673e404SJohn Birrell tdp->t_ardef->ad_idxtype = tdarr[cta->cta_index]; 11251673e404SJohn Birrell tdp->t_ardef->ad_nelems = cta->cta_nelems; 11261673e404SJohn Birrell break; 11271673e404SJohn Birrell 11281673e404SJohn Birrell case CTF_K_STRUCT: 11291673e404SJohn Birrell case CTF_K_UNION: 11301673e404SJohn Birrell tdp->t_type = (kind == CTF_K_STRUCT ? STRUCT : UNION); 11311673e404SJohn Birrell tdp->t_size = size; 11321673e404SJohn Birrell 11331673e404SJohn Birrell if (size < CTF_LSTRUCT_THRESH) { 11341673e404SJohn Birrell for (i = 0, mpp = &tdp->t_members; i < vlen; 11351673e404SJohn Birrell i++, mpp = &((*mpp)->ml_next)) { 11364cc75139SJohn Birrell v = (void *) dptr; 11374cc75139SJohn Birrell ctf_member_t *ctm = v; 11381673e404SJohn Birrell dptr += sizeof (ctf_member_t); 11391673e404SJohn Birrell 11401673e404SJohn Birrell *mpp = xmalloc(sizeof (mlist_t)); 11411673e404SJohn Birrell (*mpp)->ml_name = xstrdup(sbuf + 11421673e404SJohn Birrell ctm->ctm_name); 11431673e404SJohn Birrell (*mpp)->ml_type = tdarr[ctm->ctm_type]; 11441673e404SJohn Birrell (*mpp)->ml_offset = ctm->ctm_offset; 11451673e404SJohn Birrell (*mpp)->ml_size = 0; 11461673e404SJohn Birrell } 11471673e404SJohn Birrell } else { 11481673e404SJohn Birrell for (i = 0, mpp = &tdp->t_members; i < vlen; 11491673e404SJohn Birrell i++, mpp = &((*mpp)->ml_next)) { 11504cc75139SJohn Birrell v = (void *) dptr; 11514cc75139SJohn Birrell ctf_lmember_t *ctlm = v; 11521673e404SJohn Birrell dptr += sizeof (ctf_lmember_t); 11531673e404SJohn Birrell 11541673e404SJohn Birrell *mpp = xmalloc(sizeof (mlist_t)); 11551673e404SJohn Birrell (*mpp)->ml_name = xstrdup(sbuf + 11561673e404SJohn Birrell ctlm->ctlm_name); 11571673e404SJohn Birrell (*mpp)->ml_type = 11581673e404SJohn Birrell tdarr[ctlm->ctlm_type]; 11591673e404SJohn Birrell (*mpp)->ml_offset = 11601673e404SJohn Birrell (int)CTF_LMEM_OFFSET(ctlm); 11611673e404SJohn Birrell (*mpp)->ml_size = 0; 11621673e404SJohn Birrell } 11631673e404SJohn Birrell } 11641673e404SJohn Birrell 11651673e404SJohn Birrell *mpp = NULL; 11661673e404SJohn Birrell break; 11671673e404SJohn Birrell 11681673e404SJohn Birrell case CTF_K_ENUM: 11691673e404SJohn Birrell tdp->t_type = ENUM; 11701673e404SJohn Birrell tdp->t_size = size; 11711673e404SJohn Birrell 11721673e404SJohn Birrell for (i = 0, epp = &tdp->t_emem; i < vlen; 11731673e404SJohn Birrell i++, epp = &((*epp)->el_next)) { 11744cc75139SJohn Birrell v = (void *) dptr; 11754cc75139SJohn Birrell cte = v; 11761673e404SJohn Birrell dptr += sizeof (ctf_enum_t); 11771673e404SJohn Birrell 11781673e404SJohn Birrell *epp = xmalloc(sizeof (elist_t)); 11791673e404SJohn Birrell (*epp)->el_name = xstrdup(sbuf + cte->cte_name); 11801673e404SJohn Birrell (*epp)->el_number = cte->cte_value; 11811673e404SJohn Birrell } 11821673e404SJohn Birrell *epp = NULL; 11831673e404SJohn Birrell break; 11841673e404SJohn Birrell 11851673e404SJohn Birrell case CTF_K_FORWARD: 11861673e404SJohn Birrell tdp->t_type = FORWARD; 11871673e404SJohn Birrell list_add(&td->td_fwdlist, tdp); 11881673e404SJohn Birrell break; 11891673e404SJohn Birrell 11901673e404SJohn Birrell case CTF_K_TYPEDEF: 11911673e404SJohn Birrell tdp->t_type = TYPEDEF; 11921673e404SJohn Birrell tdp->t_tdesc = tdarr[ctt->ctt_type]; 11931673e404SJohn Birrell break; 11941673e404SJohn Birrell 11951673e404SJohn Birrell case CTF_K_VOLATILE: 11961673e404SJohn Birrell tdp->t_type = VOLATILE; 11971673e404SJohn Birrell tdp->t_tdesc = tdarr[ctt->ctt_type]; 11981673e404SJohn Birrell break; 11991673e404SJohn Birrell 12001673e404SJohn Birrell case CTF_K_CONST: 12011673e404SJohn Birrell tdp->t_type = CONST; 12021673e404SJohn Birrell tdp->t_tdesc = tdarr[ctt->ctt_type]; 12031673e404SJohn Birrell break; 12041673e404SJohn Birrell 12051673e404SJohn Birrell case CTF_K_FUNCTION: 12061673e404SJohn Birrell tdp->t_type = FUNCTION; 12071673e404SJohn Birrell tdp->t_fndef = xcalloc(sizeof (fndef_t)); 12081673e404SJohn Birrell tdp->t_fndef->fn_ret = tdarr[ctt->ctt_type]; 12091673e404SJohn Birrell 12104cc75139SJohn Birrell v = (void *) (dptr + (sizeof (ushort_t) * (vlen - 1))); 12114cc75139SJohn Birrell if (vlen > 0 && *(ushort_t *)v == 0) 12121673e404SJohn Birrell tdp->t_fndef->fn_vargs = 1; 12131673e404SJohn Birrell 12141673e404SJohn Birrell tdp->t_fndef->fn_nargs = vlen - tdp->t_fndef->fn_vargs; 12151673e404SJohn Birrell tdp->t_fndef->fn_args = xcalloc(sizeof (tdesc_t) * 12161673e404SJohn Birrell vlen - tdp->t_fndef->fn_vargs); 12171673e404SJohn Birrell 12181673e404SJohn Birrell for (i = 0; i < vlen; i++) { 12194cc75139SJohn Birrell v = (void *) dptr; 12204cc75139SJohn Birrell argid = *(ushort_t *)v; 12211673e404SJohn Birrell dptr += sizeof (ushort_t); 12221673e404SJohn Birrell 12231673e404SJohn Birrell if (argid != 0) 12241673e404SJohn Birrell tdp->t_fndef->fn_args[i] = tdarr[argid]; 12251673e404SJohn Birrell } 12261673e404SJohn Birrell 12271673e404SJohn Birrell if (vlen & 1) 12281673e404SJohn Birrell dptr += sizeof (ushort_t); 12291673e404SJohn Birrell break; 12301673e404SJohn Birrell 12311673e404SJohn Birrell case CTF_K_RESTRICT: 12321673e404SJohn Birrell tdp->t_type = RESTRICT; 12331673e404SJohn Birrell tdp->t_tdesc = tdarr[ctt->ctt_type]; 12341673e404SJohn Birrell break; 12351673e404SJohn Birrell 12361673e404SJohn Birrell case CTF_K_UNKNOWN: 12371673e404SJohn Birrell break; 12381673e404SJohn Birrell 12391673e404SJohn Birrell default: 12401673e404SJohn Birrell warning("Can't parse unknown CTF type %d\n", kind); 12411673e404SJohn Birrell } 12421673e404SJohn Birrell 12431673e404SJohn Birrell if (CTF_INFO_ISROOT(ctt->ctt_info)) { 12441673e404SJohn Birrell iidesc_t *ii = iidesc_new(tdp->t_name); 12451673e404SJohn Birrell if (tdp->t_type == STRUCT || tdp->t_type == UNION || 12461673e404SJohn Birrell tdp->t_type == ENUM) 12471673e404SJohn Birrell ii->ii_type = II_SOU; 12481673e404SJohn Birrell else 12491673e404SJohn Birrell ii->ii_type = II_TYPE; 12501673e404SJohn Birrell ii->ii_dtype = tdp; 12511673e404SJohn Birrell hash_add(td->td_iihash, ii); 12521673e404SJohn Birrell 12531673e404SJohn Birrell iicnt++; 12541673e404SJohn Birrell } 12551673e404SJohn Birrell 12561673e404SJohn Birrell debug(3, "Resurrected %d %stype %s (%d)\n", tdp->t_type, 12571673e404SJohn Birrell (CTF_INFO_ISROOT(ctt->ctt_info) ? "root " : ""), 12581673e404SJohn Birrell tdesc_name(tdp), tdp->t_id); 12591673e404SJohn Birrell } 12601673e404SJohn Birrell 12611673e404SJohn Birrell debug(3, "Resurrected %d types (%d were roots)\n", tcnt, iicnt); 12621673e404SJohn Birrell } 12631673e404SJohn Birrell 12641673e404SJohn Birrell /* 12651673e404SJohn Birrell * For lack of other inspiration, we're going to take the boring route. We 12661673e404SJohn Birrell * count the number of types. This lets us malloc that many tdesc structs 12671673e404SJohn Birrell * before we start filling them in. This has the advantage of allowing us to 12681673e404SJohn Birrell * avoid a merge-esque remap step. 12691673e404SJohn Birrell */ 12701673e404SJohn Birrell static tdata_t * 12711673e404SJohn Birrell ctf_parse(ctf_header_t *h, caddr_t buf, symit_data_t *si, char *label) 12721673e404SJohn Birrell { 12731673e404SJohn Birrell tdata_t *td = tdata_new(); 12741673e404SJohn Birrell tdesc_t **tdarr; 1275*69718b78SPedro F. Giffuni int ntypes = count_types(h, buf); 12761673e404SJohn Birrell int idx, i; 12771673e404SJohn Birrell 12781673e404SJohn Birrell /* shudder */ 12791673e404SJohn Birrell tdarr = xcalloc(sizeof (tdesc_t *) * (ntypes + 1)); 12801673e404SJohn Birrell tdarr[0] = NULL; 12811673e404SJohn Birrell for (i = 1; i <= ntypes; i++) { 12821673e404SJohn Birrell tdarr[i] = xcalloc(sizeof (tdesc_t)); 12831673e404SJohn Birrell tdarr[i]->t_id = i; 12841673e404SJohn Birrell } 12851673e404SJohn Birrell 12861673e404SJohn Birrell td->td_parlabel = xstrdup(buf + h->cth_stroff + h->cth_parlabel); 12871673e404SJohn Birrell 12881673e404SJohn Birrell /* we have the technology - we can rebuild them */ 12891673e404SJohn Birrell idx = resurrect_labels(h, td, buf, label); 12901673e404SJohn Birrell 12911673e404SJohn Birrell resurrect_objects(h, td, tdarr, ntypes + 1, buf, si); 12921673e404SJohn Birrell resurrect_functions(h, td, tdarr, ntypes + 1, buf, si); 12931673e404SJohn Birrell resurrect_types(h, td, tdarr, ntypes + 1, buf, idx); 12941673e404SJohn Birrell 12951673e404SJohn Birrell free(tdarr); 12961673e404SJohn Birrell 12971673e404SJohn Birrell td->td_nextid = ntypes + 1; 12981673e404SJohn Birrell 12991673e404SJohn Birrell return (td); 13001673e404SJohn Birrell } 13011673e404SJohn Birrell 13021673e404SJohn Birrell static size_t 13031673e404SJohn Birrell decompress_ctf(caddr_t cbuf, size_t cbufsz, caddr_t dbuf, size_t dbufsz) 13041673e404SJohn Birrell { 13051673e404SJohn Birrell z_stream zstr; 13061673e404SJohn Birrell int rc; 13071673e404SJohn Birrell 13081673e404SJohn Birrell zstr.zalloc = (alloc_func)0; 13091673e404SJohn Birrell zstr.zfree = (free_func)0; 13101673e404SJohn Birrell zstr.opaque = (voidpf)0; 13111673e404SJohn Birrell 13121673e404SJohn Birrell zstr.next_in = (Bytef *)cbuf; 13131673e404SJohn Birrell zstr.avail_in = cbufsz; 13141673e404SJohn Birrell zstr.next_out = (Bytef *)dbuf; 13151673e404SJohn Birrell zstr.avail_out = dbufsz; 13161673e404SJohn Birrell 13171673e404SJohn Birrell if ((rc = inflateInit(&zstr)) != Z_OK || 13181673e404SJohn Birrell (rc = inflate(&zstr, Z_NO_FLUSH)) != Z_STREAM_END || 13191673e404SJohn Birrell (rc = inflateEnd(&zstr)) != Z_OK) { 13201673e404SJohn Birrell warning("CTF decompress zlib error %s\n", zError(rc)); 13214cc75139SJohn Birrell return (0); 13221673e404SJohn Birrell } 13231673e404SJohn Birrell 13241673e404SJohn Birrell debug(3, "reflated %lu bytes to %lu, pointer at %d\n", 13251673e404SJohn Birrell zstr.total_in, zstr.total_out, (caddr_t)zstr.next_in - cbuf); 13261673e404SJohn Birrell 13271673e404SJohn Birrell return (zstr.total_out); 13281673e404SJohn Birrell } 13291673e404SJohn Birrell 13301673e404SJohn Birrell /* 13311673e404SJohn Birrell * Reconstruct the type tree from a given buffer of CTF data. Only the types 13321673e404SJohn Birrell * up to the type associated with the provided label, inclusive, will be 13331673e404SJohn Birrell * reconstructed. If a NULL label is provided, all types will be reconstructed. 13341673e404SJohn Birrell * 13351673e404SJohn Birrell * This function won't work on files that have been uniquified. 13361673e404SJohn Birrell */ 13371673e404SJohn Birrell tdata_t * 13381673e404SJohn Birrell ctf_load(char *file, caddr_t buf, size_t bufsz, symit_data_t *si, char *label) 13391673e404SJohn Birrell { 13401673e404SJohn Birrell ctf_header_t *h; 13411673e404SJohn Birrell caddr_t ctfdata; 13421673e404SJohn Birrell size_t ctfdatasz; 13431673e404SJohn Birrell tdata_t *td; 13441673e404SJohn Birrell 13451673e404SJohn Birrell curfile = file; 13461673e404SJohn Birrell 13471673e404SJohn Birrell if (bufsz < sizeof (ctf_header_t)) 13481673e404SJohn Birrell parseterminate("Corrupt CTF - short header"); 13491673e404SJohn Birrell 13504cc75139SJohn Birrell void *v = (void *) buf; 13514cc75139SJohn Birrell h = v; 13521673e404SJohn Birrell buf += sizeof (ctf_header_t); 13531673e404SJohn Birrell bufsz -= sizeof (ctf_header_t); 13541673e404SJohn Birrell 13551673e404SJohn Birrell if (h->cth_magic != CTF_MAGIC) 13561673e404SJohn Birrell parseterminate("Corrupt CTF - bad magic 0x%x", h->cth_magic); 13571673e404SJohn Birrell 13581673e404SJohn Birrell if (h->cth_version != CTF_VERSION) 13591673e404SJohn Birrell parseterminate("Unknown CTF version %d", h->cth_version); 13601673e404SJohn Birrell 13611673e404SJohn Birrell ctfdatasz = h->cth_stroff + h->cth_strlen; 13621673e404SJohn Birrell if (h->cth_flags & CTF_F_COMPRESS) { 13631673e404SJohn Birrell size_t actual; 13641673e404SJohn Birrell 13651673e404SJohn Birrell ctfdata = xmalloc(ctfdatasz); 13661673e404SJohn Birrell if ((actual = decompress_ctf(buf, bufsz, ctfdata, ctfdatasz)) != 13671673e404SJohn Birrell ctfdatasz) { 13681673e404SJohn Birrell parseterminate("Corrupt CTF - short decompression " 13691673e404SJohn Birrell "(was %d, expecting %d)", actual, ctfdatasz); 13701673e404SJohn Birrell } 13711673e404SJohn Birrell } else { 13721673e404SJohn Birrell ctfdata = buf; 13731673e404SJohn Birrell ctfdatasz = bufsz; 13741673e404SJohn Birrell } 13751673e404SJohn Birrell 13761673e404SJohn Birrell td = ctf_parse(h, ctfdata, si, label); 13771673e404SJohn Birrell 13781673e404SJohn Birrell if (h->cth_flags & CTF_F_COMPRESS) 13791673e404SJohn Birrell free(ctfdata); 13801673e404SJohn Birrell 13811673e404SJohn Birrell curfile = NULL; 13821673e404SJohn Birrell 13831673e404SJohn Birrell return (td); 13841673e404SJohn Birrell } 1385