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