17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 22e4586ebfSmws 237c478bd9Sstevel@tonic-gate /* 24e4586ebfSmws * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 270a47c91cSRobert Mustacchi /* 28*7fd79137SRobert Mustacchi * Copyright (c) 2015, Joyent, Inc. All rights reserved. 290a47c91cSRobert Mustacchi */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #include <ctf_impl.h> 327c478bd9Sstevel@tonic-gate #include <sys/mman.h> 337c478bd9Sstevel@tonic-gate #include <sys/zmod.h> 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate static const ctf_dmodel_t _libctf_models[] = { 367c478bd9Sstevel@tonic-gate { "ILP32", CTF_MODEL_ILP32, 4, 1, 2, 4, 4 }, 377c478bd9Sstevel@tonic-gate { "LP64", CTF_MODEL_LP64, 8, 1, 2, 4, 8 }, 387c478bd9Sstevel@tonic-gate { NULL, 0, 0, 0, 0, 0, 0 } 397c478bd9Sstevel@tonic-gate }; 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate const char _CTF_SECTION[] = ".SUNW_ctf"; 427c478bd9Sstevel@tonic-gate const char _CTF_NULLSTR[] = ""; 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate int _libctf_version = CTF_VERSION; /* library client version */ 457c478bd9Sstevel@tonic-gate int _libctf_debug = 0; /* debugging messages enabled */ 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate static ushort_t 487c478bd9Sstevel@tonic-gate get_kind_v1(ushort_t info) 497c478bd9Sstevel@tonic-gate { 507c478bd9Sstevel@tonic-gate return (CTF_INFO_KIND_V1(info)); 517c478bd9Sstevel@tonic-gate } 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate static ushort_t 547c478bd9Sstevel@tonic-gate get_kind_v2(ushort_t info) 557c478bd9Sstevel@tonic-gate { 567c478bd9Sstevel@tonic-gate return (CTF_INFO_KIND(info)); 577c478bd9Sstevel@tonic-gate } 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate static ushort_t 607c478bd9Sstevel@tonic-gate get_root_v1(ushort_t info) 617c478bd9Sstevel@tonic-gate { 627c478bd9Sstevel@tonic-gate return (CTF_INFO_ISROOT_V1(info)); 637c478bd9Sstevel@tonic-gate } 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate static ushort_t 667c478bd9Sstevel@tonic-gate get_root_v2(ushort_t info) 677c478bd9Sstevel@tonic-gate { 687c478bd9Sstevel@tonic-gate return (CTF_INFO_ISROOT(info)); 697c478bd9Sstevel@tonic-gate } 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate static ushort_t 727c478bd9Sstevel@tonic-gate get_vlen_v1(ushort_t info) 737c478bd9Sstevel@tonic-gate { 747c478bd9Sstevel@tonic-gate return (CTF_INFO_VLEN_V1(info)); 757c478bd9Sstevel@tonic-gate } 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate static ushort_t 787c478bd9Sstevel@tonic-gate get_vlen_v2(ushort_t info) 797c478bd9Sstevel@tonic-gate { 807c478bd9Sstevel@tonic-gate return (CTF_INFO_VLEN(info)); 817c478bd9Sstevel@tonic-gate } 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate static const ctf_fileops_t ctf_fileops[] = { 847c478bd9Sstevel@tonic-gate { NULL, NULL }, 857c478bd9Sstevel@tonic-gate { get_kind_v1, get_root_v1, get_vlen_v1 }, 867c478bd9Sstevel@tonic-gate { get_kind_v2, get_root_v2, get_vlen_v2 }, 877c478bd9Sstevel@tonic-gate }; 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate /* 907c478bd9Sstevel@tonic-gate * Convert a 32-bit ELF symbol into GElf (Elf64) and return a pointer to it. 917c478bd9Sstevel@tonic-gate */ 927c478bd9Sstevel@tonic-gate static Elf64_Sym * 937c478bd9Sstevel@tonic-gate sym_to_gelf(const Elf32_Sym *src, Elf64_Sym *dst) 947c478bd9Sstevel@tonic-gate { 957c478bd9Sstevel@tonic-gate dst->st_name = src->st_name; 967c478bd9Sstevel@tonic-gate dst->st_value = src->st_value; 977c478bd9Sstevel@tonic-gate dst->st_size = src->st_size; 987c478bd9Sstevel@tonic-gate dst->st_info = src->st_info; 997c478bd9Sstevel@tonic-gate dst->st_other = src->st_other; 1007c478bd9Sstevel@tonic-gate dst->st_shndx = src->st_shndx; 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate return (dst); 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate /* 1067c478bd9Sstevel@tonic-gate * Initialize the symtab translation table by filling each entry with the 1077c478bd9Sstevel@tonic-gate * offset of the CTF type or function data corresponding to each STT_FUNC or 1087c478bd9Sstevel@tonic-gate * STT_OBJECT entry in the symbol table. 1097c478bd9Sstevel@tonic-gate */ 1107c478bd9Sstevel@tonic-gate static int 1117c478bd9Sstevel@tonic-gate init_symtab(ctf_file_t *fp, const ctf_header_t *hp, 1127c478bd9Sstevel@tonic-gate const ctf_sect_t *sp, const ctf_sect_t *strp) 1137c478bd9Sstevel@tonic-gate { 1147c478bd9Sstevel@tonic-gate const uchar_t *symp = sp->cts_data; 1157c478bd9Sstevel@tonic-gate uint_t *xp = fp->ctf_sxlate; 1167c478bd9Sstevel@tonic-gate uint_t *xend = xp + fp->ctf_nsyms; 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate uint_t objtoff = hp->cth_objtoff; 1197c478bd9Sstevel@tonic-gate uint_t funcoff = hp->cth_funcoff; 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate ushort_t info, vlen; 1227c478bd9Sstevel@tonic-gate Elf64_Sym sym, *gsp; 1237c478bd9Sstevel@tonic-gate const char *name; 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate /* 1267c478bd9Sstevel@tonic-gate * The CTF data object and function type sections are ordered to match 1277c478bd9Sstevel@tonic-gate * the relative order of the respective symbol types in the symtab. 1287c478bd9Sstevel@tonic-gate * If no type information is available for a symbol table entry, a 1297c478bd9Sstevel@tonic-gate * pad is inserted in the CTF section. As a further optimization, 1307c478bd9Sstevel@tonic-gate * anonymous or undefined symbols are omitted from the CTF data. 1317c478bd9Sstevel@tonic-gate */ 1327c478bd9Sstevel@tonic-gate for (; xp < xend; xp++, symp += sp->cts_entsize) { 1337c478bd9Sstevel@tonic-gate if (sp->cts_entsize == sizeof (Elf32_Sym)) 1347c478bd9Sstevel@tonic-gate gsp = sym_to_gelf((Elf32_Sym *)(uintptr_t)symp, &sym); 1357c478bd9Sstevel@tonic-gate else 1367c478bd9Sstevel@tonic-gate gsp = (Elf64_Sym *)(uintptr_t)symp; 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate if (gsp->st_name < strp->cts_size) 1397c478bd9Sstevel@tonic-gate name = (const char *)strp->cts_data + gsp->st_name; 1407c478bd9Sstevel@tonic-gate else 1417c478bd9Sstevel@tonic-gate name = _CTF_NULLSTR; 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate if (gsp->st_name == 0 || gsp->st_shndx == SHN_UNDEF || 1447c478bd9Sstevel@tonic-gate strcmp(name, "_START_") == 0 || 1457c478bd9Sstevel@tonic-gate strcmp(name, "_END_") == 0) { 1467c478bd9Sstevel@tonic-gate *xp = -1u; 1477c478bd9Sstevel@tonic-gate continue; 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate switch (ELF64_ST_TYPE(gsp->st_info)) { 1517c478bd9Sstevel@tonic-gate case STT_OBJECT: 1527c478bd9Sstevel@tonic-gate if (objtoff >= hp->cth_funcoff || 1537c478bd9Sstevel@tonic-gate (gsp->st_shndx == SHN_ABS && gsp->st_value == 0)) { 1547c478bd9Sstevel@tonic-gate *xp = -1u; 1557c478bd9Sstevel@tonic-gate break; 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate *xp = objtoff; 1597c478bd9Sstevel@tonic-gate objtoff += sizeof (ushort_t); 1607c478bd9Sstevel@tonic-gate break; 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate case STT_FUNC: 1637c478bd9Sstevel@tonic-gate if (funcoff >= hp->cth_typeoff) { 1647c478bd9Sstevel@tonic-gate *xp = -1u; 1657c478bd9Sstevel@tonic-gate break; 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate *xp = funcoff; 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate info = *(ushort_t *)((uintptr_t)fp->ctf_buf + funcoff); 1717c478bd9Sstevel@tonic-gate vlen = LCTF_INFO_VLEN(fp, info); 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate /* 1747c478bd9Sstevel@tonic-gate * If we encounter a zero pad at the end, just skip it. 1757c478bd9Sstevel@tonic-gate * Otherwise skip over the function and its return type 1767c478bd9Sstevel@tonic-gate * (+2) and the argument list (vlen). 1777c478bd9Sstevel@tonic-gate */ 1787c478bd9Sstevel@tonic-gate if (LCTF_INFO_KIND(fp, info) == CTF_K_UNKNOWN && 1797c478bd9Sstevel@tonic-gate vlen == 0) 1807c478bd9Sstevel@tonic-gate funcoff += sizeof (ushort_t); /* skip pad */ 1817c478bd9Sstevel@tonic-gate else 1827c478bd9Sstevel@tonic-gate funcoff += sizeof (ushort_t) * (vlen + 2); 1837c478bd9Sstevel@tonic-gate break; 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate default: 1867c478bd9Sstevel@tonic-gate *xp = -1u; 1877c478bd9Sstevel@tonic-gate break; 1887c478bd9Sstevel@tonic-gate } 1897c478bd9Sstevel@tonic-gate } 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate ctf_dprintf("loaded %lu symtab entries\n", fp->ctf_nsyms); 1927c478bd9Sstevel@tonic-gate return (0); 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate /* 1967c478bd9Sstevel@tonic-gate * Initialize the type ID translation table with the byte offset of each type, 1977c478bd9Sstevel@tonic-gate * and initialize the hash tables of each named type. 1987c478bd9Sstevel@tonic-gate */ 1997c478bd9Sstevel@tonic-gate static int 200e4586ebfSmws init_types(ctf_file_t *fp, const ctf_header_t *cth) 2017c478bd9Sstevel@tonic-gate { 2027c478bd9Sstevel@tonic-gate /* LINTED - pointer alignment */ 203e4586ebfSmws const ctf_type_t *tbuf = (ctf_type_t *)(fp->ctf_buf + cth->cth_typeoff); 2047c478bd9Sstevel@tonic-gate /* LINTED - pointer alignment */ 205e4586ebfSmws const ctf_type_t *tend = (ctf_type_t *)(fp->ctf_buf + cth->cth_stroff); 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate ulong_t pop[CTF_K_MAX + 1] = { 0 }; 2087c478bd9Sstevel@tonic-gate const ctf_type_t *tp; 209e4586ebfSmws ctf_hash_t *hp; 2107c478bd9Sstevel@tonic-gate ushort_t id, dst; 2117c478bd9Sstevel@tonic-gate uint_t *xp; 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate /* 2147c478bd9Sstevel@tonic-gate * We initially determine whether the container is a child or a parent 2157c478bd9Sstevel@tonic-gate * based on the value of cth_parname. To support containers that pre- 2167c478bd9Sstevel@tonic-gate * date cth_parname, we also scan the types themselves for references 2177c478bd9Sstevel@tonic-gate * to values in the range reserved for child types in our first pass. 2187c478bd9Sstevel@tonic-gate */ 219e4586ebfSmws int child = cth->cth_parname != 0; 2207c478bd9Sstevel@tonic-gate int nlstructs = 0, nlunions = 0; 2217c478bd9Sstevel@tonic-gate int err; 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate /* 2247c478bd9Sstevel@tonic-gate * We make two passes through the entire type section. In this first 2257c478bd9Sstevel@tonic-gate * pass, we count the number of each type and the total number of types. 2267c478bd9Sstevel@tonic-gate */ 2277c478bd9Sstevel@tonic-gate for (tp = tbuf; tp < tend; fp->ctf_typemax++) { 2287c478bd9Sstevel@tonic-gate ushort_t kind = LCTF_INFO_KIND(fp, tp->ctt_info); 2297c478bd9Sstevel@tonic-gate ulong_t vlen = LCTF_INFO_VLEN(fp, tp->ctt_info); 2307c478bd9Sstevel@tonic-gate ssize_t size, increment; 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate size_t vbytes; 2337c478bd9Sstevel@tonic-gate uint_t n; 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate (void) ctf_get_ctt_size(fp, tp, &size, &increment); 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate switch (kind) { 2387c478bd9Sstevel@tonic-gate case CTF_K_INTEGER: 2397c478bd9Sstevel@tonic-gate case CTF_K_FLOAT: 2407c478bd9Sstevel@tonic-gate vbytes = sizeof (uint_t); 2417c478bd9Sstevel@tonic-gate break; 2427c478bd9Sstevel@tonic-gate case CTF_K_ARRAY: 2437c478bd9Sstevel@tonic-gate vbytes = sizeof (ctf_array_t); 2447c478bd9Sstevel@tonic-gate break; 2457c478bd9Sstevel@tonic-gate case CTF_K_FUNCTION: 2467c478bd9Sstevel@tonic-gate vbytes = sizeof (ushort_t) * (vlen + (vlen & 1)); 2477c478bd9Sstevel@tonic-gate break; 2487c478bd9Sstevel@tonic-gate case CTF_K_STRUCT: 2497c478bd9Sstevel@tonic-gate case CTF_K_UNION: 2507c478bd9Sstevel@tonic-gate if (fp->ctf_version == CTF_VERSION_1 || 2517c478bd9Sstevel@tonic-gate size < CTF_LSTRUCT_THRESH) { 2527c478bd9Sstevel@tonic-gate ctf_member_t *mp = (ctf_member_t *) 2537c478bd9Sstevel@tonic-gate ((uintptr_t)tp + increment); 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate vbytes = sizeof (ctf_member_t) * vlen; 2567c478bd9Sstevel@tonic-gate for (n = vlen; n != 0; n--, mp++) 2577c478bd9Sstevel@tonic-gate child |= CTF_TYPE_ISCHILD(mp->ctm_type); 2587c478bd9Sstevel@tonic-gate } else { 2597c478bd9Sstevel@tonic-gate ctf_lmember_t *lmp = (ctf_lmember_t *) 2607c478bd9Sstevel@tonic-gate ((uintptr_t)tp + increment); 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate vbytes = sizeof (ctf_lmember_t) * vlen; 2637c478bd9Sstevel@tonic-gate for (n = vlen; n != 0; n--, lmp++) 2647c478bd9Sstevel@tonic-gate child |= 2657c478bd9Sstevel@tonic-gate CTF_TYPE_ISCHILD(lmp->ctlm_type); 2667c478bd9Sstevel@tonic-gate } 2677c478bd9Sstevel@tonic-gate break; 2687c478bd9Sstevel@tonic-gate case CTF_K_ENUM: 2697c478bd9Sstevel@tonic-gate vbytes = sizeof (ctf_enum_t) * vlen; 2707c478bd9Sstevel@tonic-gate break; 2717c478bd9Sstevel@tonic-gate case CTF_K_FORWARD: 272e4586ebfSmws /* 273e4586ebfSmws * For forward declarations, ctt_type is the CTF_K_* 274e4586ebfSmws * kind for the tag, so bump that population count too. 275e4586ebfSmws * If ctt_type is unknown, treat the tag as a struct. 276e4586ebfSmws */ 277e4586ebfSmws if (tp->ctt_type == CTF_K_UNKNOWN || 278e4586ebfSmws tp->ctt_type >= CTF_K_MAX) 279e4586ebfSmws pop[CTF_K_STRUCT]++; 280e4586ebfSmws else 281e4586ebfSmws pop[tp->ctt_type]++; 282e4586ebfSmws /*FALLTHRU*/ 2837c478bd9Sstevel@tonic-gate case CTF_K_UNKNOWN: 2847c478bd9Sstevel@tonic-gate vbytes = 0; 2857c478bd9Sstevel@tonic-gate break; 2867c478bd9Sstevel@tonic-gate case CTF_K_POINTER: 2877c478bd9Sstevel@tonic-gate case CTF_K_TYPEDEF: 2887c478bd9Sstevel@tonic-gate case CTF_K_VOLATILE: 2897c478bd9Sstevel@tonic-gate case CTF_K_CONST: 2907c478bd9Sstevel@tonic-gate case CTF_K_RESTRICT: 2917c478bd9Sstevel@tonic-gate child |= CTF_TYPE_ISCHILD(tp->ctt_type); 2927c478bd9Sstevel@tonic-gate vbytes = 0; 2937c478bd9Sstevel@tonic-gate break; 2947c478bd9Sstevel@tonic-gate default: 2957c478bd9Sstevel@tonic-gate ctf_dprintf("detected invalid CTF kind -- %u\n", kind); 2967c478bd9Sstevel@tonic-gate return (ECTF_CORRUPT); 2977c478bd9Sstevel@tonic-gate } 2987c478bd9Sstevel@tonic-gate tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes); 2997c478bd9Sstevel@tonic-gate pop[kind]++; 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate /* 3037c478bd9Sstevel@tonic-gate * If we detected a reference to a child type ID, then we know this 3047c478bd9Sstevel@tonic-gate * container is a child and may have a parent's types imported later. 3057c478bd9Sstevel@tonic-gate */ 3067c478bd9Sstevel@tonic-gate if (child) { 3077c478bd9Sstevel@tonic-gate ctf_dprintf("CTF container %p is a child\n", (void *)fp); 3087c478bd9Sstevel@tonic-gate fp->ctf_flags |= LCTF_CHILD; 3097c478bd9Sstevel@tonic-gate } else 3107c478bd9Sstevel@tonic-gate ctf_dprintf("CTF container %p is a parent\n", (void *)fp); 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate /* 3137c478bd9Sstevel@tonic-gate * Now that we've counted up the number of each type, we can allocate 3147c478bd9Sstevel@tonic-gate * the hash tables, type translation table, and pointer table. 3157c478bd9Sstevel@tonic-gate */ 316e4586ebfSmws if ((err = ctf_hash_create(&fp->ctf_structs, pop[CTF_K_STRUCT])) != 0) 3177c478bd9Sstevel@tonic-gate return (err); 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate if ((err = ctf_hash_create(&fp->ctf_unions, pop[CTF_K_UNION])) != 0) 3207c478bd9Sstevel@tonic-gate return (err); 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate if ((err = ctf_hash_create(&fp->ctf_enums, pop[CTF_K_ENUM])) != 0) 3237c478bd9Sstevel@tonic-gate return (err); 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate if ((err = ctf_hash_create(&fp->ctf_names, 3267c478bd9Sstevel@tonic-gate pop[CTF_K_INTEGER] + pop[CTF_K_FLOAT] + pop[CTF_K_FUNCTION] + 3277c478bd9Sstevel@tonic-gate pop[CTF_K_TYPEDEF] + pop[CTF_K_POINTER] + pop[CTF_K_VOLATILE] + 3287c478bd9Sstevel@tonic-gate pop[CTF_K_CONST] + pop[CTF_K_RESTRICT])) != 0) 3297c478bd9Sstevel@tonic-gate return (err); 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate fp->ctf_txlate = ctf_alloc(sizeof (uint_t) * (fp->ctf_typemax + 1)); 3327c478bd9Sstevel@tonic-gate fp->ctf_ptrtab = ctf_alloc(sizeof (ushort_t) * (fp->ctf_typemax + 1)); 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate if (fp->ctf_txlate == NULL || fp->ctf_ptrtab == NULL) 3357c478bd9Sstevel@tonic-gate return (EAGAIN); /* memory allocation failed */ 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate xp = fp->ctf_txlate; 3387c478bd9Sstevel@tonic-gate *xp++ = 0; /* type id 0 is used as a sentinel value */ 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate bzero(fp->ctf_txlate, sizeof (uint_t) * (fp->ctf_typemax + 1)); 3417c478bd9Sstevel@tonic-gate bzero(fp->ctf_ptrtab, sizeof (ushort_t) * (fp->ctf_typemax + 1)); 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate /* 3447c478bd9Sstevel@tonic-gate * In the second pass through the types, we fill in each entry of the 3457c478bd9Sstevel@tonic-gate * type and pointer tables and add names to the appropriate hashes. 3467c478bd9Sstevel@tonic-gate */ 3477c478bd9Sstevel@tonic-gate for (id = 1, tp = tbuf; tp < tend; xp++, id++) { 3487c478bd9Sstevel@tonic-gate ushort_t kind = LCTF_INFO_KIND(fp, tp->ctt_info); 3497c478bd9Sstevel@tonic-gate ulong_t vlen = LCTF_INFO_VLEN(fp, tp->ctt_info); 3507c478bd9Sstevel@tonic-gate ssize_t size, increment; 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate const char *name; 3537c478bd9Sstevel@tonic-gate size_t vbytes; 3547c478bd9Sstevel@tonic-gate ctf_helem_t *hep; 3557c478bd9Sstevel@tonic-gate ctf_encoding_t cte; 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate (void) ctf_get_ctt_size(fp, tp, &size, &increment); 3587c478bd9Sstevel@tonic-gate name = ctf_strptr(fp, tp->ctt_name); 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate switch (kind) { 3617c478bd9Sstevel@tonic-gate case CTF_K_INTEGER: 3627c478bd9Sstevel@tonic-gate case CTF_K_FLOAT: 3637c478bd9Sstevel@tonic-gate /* 3647c478bd9Sstevel@tonic-gate * Only insert a new integer base type definition if 3657c478bd9Sstevel@tonic-gate * this type name has not been defined yet. We re-use 3667c478bd9Sstevel@tonic-gate * the names with different encodings for bit-fields. 3677c478bd9Sstevel@tonic-gate */ 3687c478bd9Sstevel@tonic-gate if ((hep = ctf_hash_lookup(&fp->ctf_names, fp, 3697c478bd9Sstevel@tonic-gate name, strlen(name))) == NULL) { 3707c478bd9Sstevel@tonic-gate err = ctf_hash_insert(&fp->ctf_names, fp, 3717c478bd9Sstevel@tonic-gate CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 3727c478bd9Sstevel@tonic-gate if (err != 0 && err != ECTF_STRTAB) 3737c478bd9Sstevel@tonic-gate return (err); 3747c478bd9Sstevel@tonic-gate } else if (ctf_type_encoding(fp, hep->h_type, 3757c478bd9Sstevel@tonic-gate &cte) == 0 && cte.cte_bits == 0) { 3767c478bd9Sstevel@tonic-gate /* 3777c478bd9Sstevel@tonic-gate * Work-around SOS8 stabs bug: replace existing 3787c478bd9Sstevel@tonic-gate * intrinsic w/ same name if it was zero bits. 3797c478bd9Sstevel@tonic-gate */ 3807c478bd9Sstevel@tonic-gate hep->h_type = CTF_INDEX_TO_TYPE(id, child); 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate vbytes = sizeof (uint_t); 3837c478bd9Sstevel@tonic-gate break; 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate case CTF_K_ARRAY: 3867c478bd9Sstevel@tonic-gate vbytes = sizeof (ctf_array_t); 3877c478bd9Sstevel@tonic-gate break; 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate case CTF_K_FUNCTION: 3907c478bd9Sstevel@tonic-gate err = ctf_hash_insert(&fp->ctf_names, fp, 3917c478bd9Sstevel@tonic-gate CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 3927c478bd9Sstevel@tonic-gate if (err != 0 && err != ECTF_STRTAB) 3937c478bd9Sstevel@tonic-gate return (err); 3947c478bd9Sstevel@tonic-gate vbytes = sizeof (ushort_t) * (vlen + (vlen & 1)); 3957c478bd9Sstevel@tonic-gate break; 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate case CTF_K_STRUCT: 398e4586ebfSmws err = ctf_hash_define(&fp->ctf_structs, fp, 3997c478bd9Sstevel@tonic-gate CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 400e4586ebfSmws 4017c478bd9Sstevel@tonic-gate if (err != 0 && err != ECTF_STRTAB) 4027c478bd9Sstevel@tonic-gate return (err); 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate if (fp->ctf_version == CTF_VERSION_1 || 4057c478bd9Sstevel@tonic-gate size < CTF_LSTRUCT_THRESH) 4067c478bd9Sstevel@tonic-gate vbytes = sizeof (ctf_member_t) * vlen; 4077c478bd9Sstevel@tonic-gate else { 4087c478bd9Sstevel@tonic-gate vbytes = sizeof (ctf_lmember_t) * vlen; 4097c478bd9Sstevel@tonic-gate nlstructs++; 4107c478bd9Sstevel@tonic-gate } 4117c478bd9Sstevel@tonic-gate break; 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate case CTF_K_UNION: 414e4586ebfSmws err = ctf_hash_define(&fp->ctf_unions, fp, 4157c478bd9Sstevel@tonic-gate CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 416e4586ebfSmws 4177c478bd9Sstevel@tonic-gate if (err != 0 && err != ECTF_STRTAB) 4187c478bd9Sstevel@tonic-gate return (err); 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate if (fp->ctf_version == CTF_VERSION_1 || 4217c478bd9Sstevel@tonic-gate size < CTF_LSTRUCT_THRESH) 4227c478bd9Sstevel@tonic-gate vbytes = sizeof (ctf_member_t) * vlen; 4237c478bd9Sstevel@tonic-gate else { 4247c478bd9Sstevel@tonic-gate vbytes = sizeof (ctf_lmember_t) * vlen; 4257c478bd9Sstevel@tonic-gate nlunions++; 4267c478bd9Sstevel@tonic-gate } 4277c478bd9Sstevel@tonic-gate break; 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate case CTF_K_ENUM: 430e4586ebfSmws err = ctf_hash_define(&fp->ctf_enums, fp, 4317c478bd9Sstevel@tonic-gate CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 432e4586ebfSmws 4337c478bd9Sstevel@tonic-gate if (err != 0 && err != ECTF_STRTAB) 4347c478bd9Sstevel@tonic-gate return (err); 435e4586ebfSmws 4367c478bd9Sstevel@tonic-gate vbytes = sizeof (ctf_enum_t) * vlen; 4377c478bd9Sstevel@tonic-gate break; 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate case CTF_K_TYPEDEF: 4407c478bd9Sstevel@tonic-gate err = ctf_hash_insert(&fp->ctf_names, fp, 4417c478bd9Sstevel@tonic-gate CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 4427c478bd9Sstevel@tonic-gate if (err != 0 && err != ECTF_STRTAB) 4437c478bd9Sstevel@tonic-gate return (err); 4447c478bd9Sstevel@tonic-gate vbytes = 0; 4457c478bd9Sstevel@tonic-gate break; 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate case CTF_K_FORWARD: 4487c478bd9Sstevel@tonic-gate /* 449e4586ebfSmws * Only insert forward tags into the given hash if the 450e4586ebfSmws * type or tag name is not already present. 4517c478bd9Sstevel@tonic-gate */ 452e4586ebfSmws switch (tp->ctt_type) { 453e4586ebfSmws case CTF_K_STRUCT: 454e4586ebfSmws hp = &fp->ctf_structs; 455e4586ebfSmws break; 456e4586ebfSmws case CTF_K_UNION: 457e4586ebfSmws hp = &fp->ctf_unions; 458e4586ebfSmws break; 459e4586ebfSmws case CTF_K_ENUM: 460e4586ebfSmws hp = &fp->ctf_enums; 461e4586ebfSmws break; 462e4586ebfSmws default: 463e4586ebfSmws hp = &fp->ctf_structs; 464e4586ebfSmws } 465e4586ebfSmws 466e4586ebfSmws if (ctf_hash_lookup(hp, fp, 4677c478bd9Sstevel@tonic-gate name, strlen(name)) == NULL) { 468e4586ebfSmws err = ctf_hash_insert(hp, fp, 4697c478bd9Sstevel@tonic-gate CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 4707c478bd9Sstevel@tonic-gate if (err != 0 && err != ECTF_STRTAB) 4717c478bd9Sstevel@tonic-gate return (err); 4727c478bd9Sstevel@tonic-gate } 4737c478bd9Sstevel@tonic-gate vbytes = 0; 4747c478bd9Sstevel@tonic-gate break; 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate case CTF_K_POINTER: 4777c478bd9Sstevel@tonic-gate /* 4787c478bd9Sstevel@tonic-gate * If the type referenced by the pointer is in this CTF 4797c478bd9Sstevel@tonic-gate * container, then store the index of the pointer type 4807c478bd9Sstevel@tonic-gate * in fp->ctf_ptrtab[ index of referenced type ]. 4817c478bd9Sstevel@tonic-gate */ 4827c478bd9Sstevel@tonic-gate if (CTF_TYPE_ISCHILD(tp->ctt_type) == child && 4837c478bd9Sstevel@tonic-gate CTF_TYPE_TO_INDEX(tp->ctt_type) <= fp->ctf_typemax) 4847c478bd9Sstevel@tonic-gate fp->ctf_ptrtab[ 4857c478bd9Sstevel@tonic-gate CTF_TYPE_TO_INDEX(tp->ctt_type)] = id; 4867c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate case CTF_K_VOLATILE: 4897c478bd9Sstevel@tonic-gate case CTF_K_CONST: 4907c478bd9Sstevel@tonic-gate case CTF_K_RESTRICT: 4917c478bd9Sstevel@tonic-gate err = ctf_hash_insert(&fp->ctf_names, fp, 4927c478bd9Sstevel@tonic-gate CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 4937c478bd9Sstevel@tonic-gate if (err != 0 && err != ECTF_STRTAB) 4947c478bd9Sstevel@tonic-gate return (err); 4957c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate default: 4987c478bd9Sstevel@tonic-gate vbytes = 0; 4997c478bd9Sstevel@tonic-gate break; 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate *xp = (uint_t)((uintptr_t)tp - (uintptr_t)fp->ctf_buf); 5037c478bd9Sstevel@tonic-gate tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes); 5047c478bd9Sstevel@tonic-gate } 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate ctf_dprintf("%lu total types processed\n", fp->ctf_typemax); 5077c478bd9Sstevel@tonic-gate ctf_dprintf("%u enum names hashed\n", ctf_hash_size(&fp->ctf_enums)); 5087c478bd9Sstevel@tonic-gate ctf_dprintf("%u struct names hashed (%d long)\n", 5097c478bd9Sstevel@tonic-gate ctf_hash_size(&fp->ctf_structs), nlstructs); 5107c478bd9Sstevel@tonic-gate ctf_dprintf("%u union names hashed (%d long)\n", 5117c478bd9Sstevel@tonic-gate ctf_hash_size(&fp->ctf_unions), nlunions); 5127c478bd9Sstevel@tonic-gate ctf_dprintf("%u base type names hashed\n", 5137c478bd9Sstevel@tonic-gate ctf_hash_size(&fp->ctf_names)); 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate /* 5167c478bd9Sstevel@tonic-gate * Make an additional pass through the pointer table to find pointers 5177c478bd9Sstevel@tonic-gate * that point to anonymous typedef nodes. If we find one, modify the 5187c478bd9Sstevel@tonic-gate * pointer table so that the pointer is also known to point to the 5197c478bd9Sstevel@tonic-gate * node that is referenced by the anonymous typedef node. 5207c478bd9Sstevel@tonic-gate */ 5217c478bd9Sstevel@tonic-gate for (id = 1; id <= fp->ctf_typemax; id++) { 5227c478bd9Sstevel@tonic-gate if ((dst = fp->ctf_ptrtab[id]) != 0) { 5237c478bd9Sstevel@tonic-gate tp = LCTF_INDEX_TO_TYPEPTR(fp, id); 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate if (LCTF_INFO_KIND(fp, tp->ctt_info) == CTF_K_TYPEDEF && 5267c478bd9Sstevel@tonic-gate strcmp(ctf_strptr(fp, tp->ctt_name), "") == 0 && 5277c478bd9Sstevel@tonic-gate CTF_TYPE_ISCHILD(tp->ctt_type) == child && 5287c478bd9Sstevel@tonic-gate CTF_TYPE_TO_INDEX(tp->ctt_type) <= fp->ctf_typemax) 5297c478bd9Sstevel@tonic-gate fp->ctf_ptrtab[ 5307c478bd9Sstevel@tonic-gate CTF_TYPE_TO_INDEX(tp->ctt_type)] = dst; 5317c478bd9Sstevel@tonic-gate } 5327c478bd9Sstevel@tonic-gate } 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate return (0); 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate /* 5387c478bd9Sstevel@tonic-gate * Decode the specified CTF buffer and optional symbol table and create a new 5397c478bd9Sstevel@tonic-gate * CTF container representing the symbolic debugging information. This code 5407c478bd9Sstevel@tonic-gate * can be used directly by the debugger, or it can be used as the engine for 5417c478bd9Sstevel@tonic-gate * ctf_fdopen() or ctf_open(), below. 5427c478bd9Sstevel@tonic-gate */ 5437c478bd9Sstevel@tonic-gate ctf_file_t * 5447c478bd9Sstevel@tonic-gate ctf_bufopen(const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, 5457c478bd9Sstevel@tonic-gate const ctf_sect_t *strsect, int *errp) 5467c478bd9Sstevel@tonic-gate { 5477c478bd9Sstevel@tonic-gate const ctf_preamble_t *pp; 5487c478bd9Sstevel@tonic-gate ctf_header_t hp; 5497c478bd9Sstevel@tonic-gate ctf_file_t *fp; 5507c478bd9Sstevel@tonic-gate void *buf, *base; 5517c478bd9Sstevel@tonic-gate size_t size, hdrsz; 5527c478bd9Sstevel@tonic-gate int err; 553*7fd79137SRobert Mustacchi uint_t hflags; 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate if (ctfsect == NULL || ((symsect == NULL) != (strsect == NULL))) 5567c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, EINVAL)); 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate if (symsect != NULL && symsect->cts_entsize != sizeof (Elf32_Sym) && 5597c478bd9Sstevel@tonic-gate symsect->cts_entsize != sizeof (Elf64_Sym)) 5607c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_SYMTAB)); 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate if (symsect != NULL && symsect->cts_data == NULL) 5637c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_SYMBAD)); 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate if (strsect != NULL && strsect->cts_data == NULL) 5667c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_STRBAD)); 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate if (ctfsect->cts_size < sizeof (ctf_preamble_t)) 5697c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_NOCTFBUF)); 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate pp = (const ctf_preamble_t *)ctfsect->cts_data; 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate ctf_dprintf("ctf_bufopen: magic=0x%x version=%u\n", 5747c478bd9Sstevel@tonic-gate pp->ctp_magic, pp->ctp_version); 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate /* 5777c478bd9Sstevel@tonic-gate * Validate each part of the CTF header (either V1 or V2). 5787c478bd9Sstevel@tonic-gate * First, we validate the preamble (common to all versions). At that 5797c478bd9Sstevel@tonic-gate * point, we know specific header version, and can validate the 5807c478bd9Sstevel@tonic-gate * version-specific parts including section offsets and alignments. 5817c478bd9Sstevel@tonic-gate */ 5827c478bd9Sstevel@tonic-gate if (pp->ctp_magic != CTF_MAGIC) 5837c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_NOCTFBUF)); 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate if (pp->ctp_version == CTF_VERSION_2) { 5867c478bd9Sstevel@tonic-gate if (ctfsect->cts_size < sizeof (ctf_header_t)) 5877c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_NOCTFBUF)); 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate bcopy(ctfsect->cts_data, &hp, sizeof (hp)); 5907c478bd9Sstevel@tonic-gate hdrsz = sizeof (ctf_header_t); 5917c478bd9Sstevel@tonic-gate 5927c478bd9Sstevel@tonic-gate } else if (pp->ctp_version == CTF_VERSION_1) { 5937c478bd9Sstevel@tonic-gate const ctf_header_v1_t *h1p = 5947c478bd9Sstevel@tonic-gate (const ctf_header_v1_t *)ctfsect->cts_data; 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate if (ctfsect->cts_size < sizeof (ctf_header_v1_t)) 5977c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_NOCTFBUF)); 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate bzero(&hp, sizeof (hp)); 6007c478bd9Sstevel@tonic-gate hp.cth_preamble = h1p->cth_preamble; 6017c478bd9Sstevel@tonic-gate hp.cth_objtoff = h1p->cth_objtoff; 6027c478bd9Sstevel@tonic-gate hp.cth_funcoff = h1p->cth_funcoff; 6037c478bd9Sstevel@tonic-gate hp.cth_typeoff = h1p->cth_typeoff; 6047c478bd9Sstevel@tonic-gate hp.cth_stroff = h1p->cth_stroff; 6057c478bd9Sstevel@tonic-gate hp.cth_strlen = h1p->cth_strlen; 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate hdrsz = sizeof (ctf_header_v1_t); 6087c478bd9Sstevel@tonic-gate } else 6097c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_CTFVERS)); 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate size = hp.cth_stroff + hp.cth_strlen; 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate ctf_dprintf("ctf_bufopen: uncompressed size=%lu\n", (ulong_t)size); 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate if (hp.cth_lbloff > size || hp.cth_objtoff > size || 6167c478bd9Sstevel@tonic-gate hp.cth_funcoff > size || hp.cth_typeoff > size || 6177c478bd9Sstevel@tonic-gate hp.cth_stroff > size) 6187c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_CORRUPT)); 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate if (hp.cth_lbloff > hp.cth_objtoff || 6217c478bd9Sstevel@tonic-gate hp.cth_objtoff > hp.cth_funcoff || 6227c478bd9Sstevel@tonic-gate hp.cth_funcoff > hp.cth_typeoff || 6237c478bd9Sstevel@tonic-gate hp.cth_typeoff > hp.cth_stroff) 6247c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_CORRUPT)); 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate if ((hp.cth_lbloff & 3) || (hp.cth_objtoff & 1) || 6277c478bd9Sstevel@tonic-gate (hp.cth_funcoff & 1) || (hp.cth_typeoff & 3)) 6287c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_CORRUPT)); 6297c478bd9Sstevel@tonic-gate 6307c478bd9Sstevel@tonic-gate /* 6317c478bd9Sstevel@tonic-gate * Once everything is determined to be valid, attempt to decompress 6327c478bd9Sstevel@tonic-gate * the CTF data buffer if it is compressed. Otherwise we just put 6337c478bd9Sstevel@tonic-gate * the data section's buffer pointer into ctf_buf, below. 6347c478bd9Sstevel@tonic-gate */ 635*7fd79137SRobert Mustacchi hflags = hp.cth_flags; 6367c478bd9Sstevel@tonic-gate if (hp.cth_flags & CTF_F_COMPRESS) { 6377c478bd9Sstevel@tonic-gate size_t srclen, dstlen; 6387c478bd9Sstevel@tonic-gate const void *src; 6397c478bd9Sstevel@tonic-gate int rc = Z_OK; 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate if (ctf_zopen(errp) == NULL) 6427c478bd9Sstevel@tonic-gate return (NULL); /* errp is set for us */ 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate if ((base = ctf_data_alloc(size + hdrsz)) == MAP_FAILED) 6457c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_ZALLOC)); 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate bcopy(ctfsect->cts_data, base, hdrsz); 6487c478bd9Sstevel@tonic-gate ((ctf_preamble_t *)base)->ctp_flags &= ~CTF_F_COMPRESS; 6497c478bd9Sstevel@tonic-gate buf = (uchar_t *)base + hdrsz; 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate src = (uchar_t *)ctfsect->cts_data + hdrsz; 6527c478bd9Sstevel@tonic-gate srclen = ctfsect->cts_size - hdrsz; 6537c478bd9Sstevel@tonic-gate dstlen = size; 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate if ((rc = z_uncompress(buf, &dstlen, src, srclen)) != Z_OK) { 6567c478bd9Sstevel@tonic-gate ctf_dprintf("zlib inflate err: %s\n", z_strerror(rc)); 6577c478bd9Sstevel@tonic-gate ctf_data_free(base, size + hdrsz); 6587c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_DECOMPRESS)); 6597c478bd9Sstevel@tonic-gate } 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate if (dstlen != size) { 6627c478bd9Sstevel@tonic-gate ctf_dprintf("zlib inflate short -- got %lu of %lu " 6637c478bd9Sstevel@tonic-gate "bytes\n", (ulong_t)dstlen, (ulong_t)size); 6647c478bd9Sstevel@tonic-gate ctf_data_free(base, size + hdrsz); 6657c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_CORRUPT)); 6667c478bd9Sstevel@tonic-gate } 6677c478bd9Sstevel@tonic-gate 6687c478bd9Sstevel@tonic-gate ctf_data_protect(base, size + hdrsz); 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate } else { 6717c478bd9Sstevel@tonic-gate base = (void *)ctfsect->cts_data; 6727c478bd9Sstevel@tonic-gate buf = (uchar_t *)base + hdrsz; 6737c478bd9Sstevel@tonic-gate } 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate /* 6767c478bd9Sstevel@tonic-gate * Once we have uncompressed and validated the CTF data buffer, we can 6777c478bd9Sstevel@tonic-gate * proceed with allocating a ctf_file_t and initializing it. 6787c478bd9Sstevel@tonic-gate */ 6797c478bd9Sstevel@tonic-gate if ((fp = ctf_alloc(sizeof (ctf_file_t))) == NULL) 6807c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, EAGAIN)); 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate bzero(fp, sizeof (ctf_file_t)); 6837c478bd9Sstevel@tonic-gate fp->ctf_version = hp.cth_version; 6847c478bd9Sstevel@tonic-gate fp->ctf_fileops = &ctf_fileops[hp.cth_version]; 685*7fd79137SRobert Mustacchi fp->ctf_hflags = hflags; 6867c478bd9Sstevel@tonic-gate bcopy(ctfsect, &fp->ctf_data, sizeof (ctf_sect_t)); 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate if (symsect != NULL) { 6897c478bd9Sstevel@tonic-gate bcopy(symsect, &fp->ctf_symtab, sizeof (ctf_sect_t)); 6907c478bd9Sstevel@tonic-gate bcopy(strsect, &fp->ctf_strtab, sizeof (ctf_sect_t)); 6917c478bd9Sstevel@tonic-gate } 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate if (fp->ctf_data.cts_name != NULL) 6947c478bd9Sstevel@tonic-gate fp->ctf_data.cts_name = ctf_strdup(fp->ctf_data.cts_name); 6957c478bd9Sstevel@tonic-gate if (fp->ctf_symtab.cts_name != NULL) 6967c478bd9Sstevel@tonic-gate fp->ctf_symtab.cts_name = ctf_strdup(fp->ctf_symtab.cts_name); 6977c478bd9Sstevel@tonic-gate if (fp->ctf_strtab.cts_name != NULL) 6987c478bd9Sstevel@tonic-gate fp->ctf_strtab.cts_name = ctf_strdup(fp->ctf_strtab.cts_name); 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate if (fp->ctf_data.cts_name == NULL) 7017c478bd9Sstevel@tonic-gate fp->ctf_data.cts_name = _CTF_NULLSTR; 7027c478bd9Sstevel@tonic-gate if (fp->ctf_symtab.cts_name == NULL) 7037c478bd9Sstevel@tonic-gate fp->ctf_symtab.cts_name = _CTF_NULLSTR; 7047c478bd9Sstevel@tonic-gate if (fp->ctf_strtab.cts_name == NULL) 7057c478bd9Sstevel@tonic-gate fp->ctf_strtab.cts_name = _CTF_NULLSTR; 7067c478bd9Sstevel@tonic-gate 7077c478bd9Sstevel@tonic-gate fp->ctf_str[CTF_STRTAB_0].cts_strs = (const char *)buf + hp.cth_stroff; 7087c478bd9Sstevel@tonic-gate fp->ctf_str[CTF_STRTAB_0].cts_len = hp.cth_strlen; 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate if (strsect != NULL) { 7117c478bd9Sstevel@tonic-gate fp->ctf_str[CTF_STRTAB_1].cts_strs = strsect->cts_data; 7127c478bd9Sstevel@tonic-gate fp->ctf_str[CTF_STRTAB_1].cts_len = strsect->cts_size; 7137c478bd9Sstevel@tonic-gate } 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate fp->ctf_base = base; 7167c478bd9Sstevel@tonic-gate fp->ctf_buf = buf; 7177c478bd9Sstevel@tonic-gate fp->ctf_size = size + hdrsz; 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate /* 7207c478bd9Sstevel@tonic-gate * If we have a parent container name and label, store the relocated 7217c478bd9Sstevel@tonic-gate * string pointers in the CTF container for easy access later. 7227c478bd9Sstevel@tonic-gate */ 7237c478bd9Sstevel@tonic-gate if (hp.cth_parlabel != 0) 7247c478bd9Sstevel@tonic-gate fp->ctf_parlabel = ctf_strptr(fp, hp.cth_parlabel); 7257c478bd9Sstevel@tonic-gate if (hp.cth_parname != 0) 7267c478bd9Sstevel@tonic-gate fp->ctf_parname = ctf_strptr(fp, hp.cth_parname); 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate ctf_dprintf("ctf_bufopen: parent name %s (label %s)\n", 7297c478bd9Sstevel@tonic-gate fp->ctf_parname ? fp->ctf_parname : "<NULL>", 7307c478bd9Sstevel@tonic-gate fp->ctf_parlabel ? fp->ctf_parlabel : "<NULL>"); 7317c478bd9Sstevel@tonic-gate 7327c478bd9Sstevel@tonic-gate /* 7337c478bd9Sstevel@tonic-gate * If we have a symbol table section, allocate and initialize 7347c478bd9Sstevel@tonic-gate * the symtab translation table, pointed to by ctf_sxlate. 7357c478bd9Sstevel@tonic-gate */ 7367c478bd9Sstevel@tonic-gate if (symsect != NULL) { 7377c478bd9Sstevel@tonic-gate fp->ctf_nsyms = symsect->cts_size / symsect->cts_entsize; 7387c478bd9Sstevel@tonic-gate fp->ctf_sxlate = ctf_alloc(fp->ctf_nsyms * sizeof (uint_t)); 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate if (fp->ctf_sxlate == NULL) { 7417c478bd9Sstevel@tonic-gate (void) ctf_set_open_errno(errp, EAGAIN); 7427c478bd9Sstevel@tonic-gate goto bad; 7437c478bd9Sstevel@tonic-gate } 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate if ((err = init_symtab(fp, &hp, symsect, strsect)) != 0) { 7467c478bd9Sstevel@tonic-gate (void) ctf_set_open_errno(errp, err); 7477c478bd9Sstevel@tonic-gate goto bad; 7487c478bd9Sstevel@tonic-gate } 7497c478bd9Sstevel@tonic-gate } 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate if ((err = init_types(fp, &hp)) != 0) { 7527c478bd9Sstevel@tonic-gate (void) ctf_set_open_errno(errp, err); 7537c478bd9Sstevel@tonic-gate goto bad; 7547c478bd9Sstevel@tonic-gate } 7557c478bd9Sstevel@tonic-gate 7567c478bd9Sstevel@tonic-gate /* 7577c478bd9Sstevel@tonic-gate * Initialize the ctf_lookup_by_name top-level dictionary. We keep an 7587c478bd9Sstevel@tonic-gate * array of type name prefixes and the corresponding ctf_hash to use. 7597c478bd9Sstevel@tonic-gate * NOTE: This code must be kept in sync with the code in ctf_update(). 7607c478bd9Sstevel@tonic-gate */ 7617c478bd9Sstevel@tonic-gate fp->ctf_lookups[0].ctl_prefix = "struct"; 7627c478bd9Sstevel@tonic-gate fp->ctf_lookups[0].ctl_len = strlen(fp->ctf_lookups[0].ctl_prefix); 7637c478bd9Sstevel@tonic-gate fp->ctf_lookups[0].ctl_hash = &fp->ctf_structs; 7647c478bd9Sstevel@tonic-gate fp->ctf_lookups[1].ctl_prefix = "union"; 7657c478bd9Sstevel@tonic-gate fp->ctf_lookups[1].ctl_len = strlen(fp->ctf_lookups[1].ctl_prefix); 7667c478bd9Sstevel@tonic-gate fp->ctf_lookups[1].ctl_hash = &fp->ctf_unions; 7677c478bd9Sstevel@tonic-gate fp->ctf_lookups[2].ctl_prefix = "enum"; 7687c478bd9Sstevel@tonic-gate fp->ctf_lookups[2].ctl_len = strlen(fp->ctf_lookups[2].ctl_prefix); 7697c478bd9Sstevel@tonic-gate fp->ctf_lookups[2].ctl_hash = &fp->ctf_enums; 7707c478bd9Sstevel@tonic-gate fp->ctf_lookups[3].ctl_prefix = _CTF_NULLSTR; 7717c478bd9Sstevel@tonic-gate fp->ctf_lookups[3].ctl_len = strlen(fp->ctf_lookups[3].ctl_prefix); 7727c478bd9Sstevel@tonic-gate fp->ctf_lookups[3].ctl_hash = &fp->ctf_names; 7737c478bd9Sstevel@tonic-gate fp->ctf_lookups[4].ctl_prefix = NULL; 7747c478bd9Sstevel@tonic-gate fp->ctf_lookups[4].ctl_len = 0; 7757c478bd9Sstevel@tonic-gate fp->ctf_lookups[4].ctl_hash = NULL; 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate if (symsect != NULL) { 7787c478bd9Sstevel@tonic-gate if (symsect->cts_entsize == sizeof (Elf64_Sym)) 7797c478bd9Sstevel@tonic-gate (void) ctf_setmodel(fp, CTF_MODEL_LP64); 7807c478bd9Sstevel@tonic-gate else 7817c478bd9Sstevel@tonic-gate (void) ctf_setmodel(fp, CTF_MODEL_ILP32); 7827c478bd9Sstevel@tonic-gate } else 7837c478bd9Sstevel@tonic-gate (void) ctf_setmodel(fp, CTF_MODEL_NATIVE); 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate fp->ctf_refcnt = 1; 7867c478bd9Sstevel@tonic-gate return (fp); 7877c478bd9Sstevel@tonic-gate 7887c478bd9Sstevel@tonic-gate bad: 7897c478bd9Sstevel@tonic-gate ctf_close(fp); 7907c478bd9Sstevel@tonic-gate return (NULL); 7917c478bd9Sstevel@tonic-gate } 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate /* 794a386cc11SRobert Mustacchi * Dupliate a ctf_file_t and its underlying section information into a new 795a386cc11SRobert Mustacchi * container. This works by copying the three ctf_sect_t's of the original 796a386cc11SRobert Mustacchi * container if they exist and passing those into ctf_bufopen. To copy those, we 797a386cc11SRobert Mustacchi * mmap anonymous memory with ctf_data_alloc and bcopy the data across. It's not 798a386cc11SRobert Mustacchi * the cheapest thing, but it's what we've got. 799a386cc11SRobert Mustacchi */ 800a386cc11SRobert Mustacchi ctf_file_t * 801a386cc11SRobert Mustacchi ctf_dup(ctf_file_t *ofp) 802a386cc11SRobert Mustacchi { 803a386cc11SRobert Mustacchi ctf_file_t *fp; 804a386cc11SRobert Mustacchi ctf_sect_t ctfsect, symsect, strsect; 805a386cc11SRobert Mustacchi ctf_sect_t *ctp, *symp, *strp; 806a386cc11SRobert Mustacchi void *cbuf, *symbuf, *strbuf; 807a386cc11SRobert Mustacchi int err; 808a386cc11SRobert Mustacchi 809a386cc11SRobert Mustacchi cbuf = symbuf = strbuf = NULL; 810a386cc11SRobert Mustacchi /* 811a386cc11SRobert Mustacchi * The ctfsect isn't allowed to not exist, but the symbol and string 812a386cc11SRobert Mustacchi * section might not. We only need to copy the data of the section, not 813a386cc11SRobert Mustacchi * the name, as ctf_bufopen will take care of that. 814a386cc11SRobert Mustacchi */ 815a386cc11SRobert Mustacchi bcopy(&ofp->ctf_data, &ctfsect, sizeof (ctf_sect_t)); 816a386cc11SRobert Mustacchi cbuf = ctf_data_alloc(ctfsect.cts_size); 817a386cc11SRobert Mustacchi if (cbuf == NULL) { 818a386cc11SRobert Mustacchi (void) ctf_set_errno(ofp, ECTF_MMAP); 819a386cc11SRobert Mustacchi return (NULL); 820a386cc11SRobert Mustacchi } 821a386cc11SRobert Mustacchi 822a386cc11SRobert Mustacchi bcopy(ctfsect.cts_data, cbuf, ctfsect.cts_size); 823a386cc11SRobert Mustacchi ctf_data_protect(cbuf, ctfsect.cts_size); 824a386cc11SRobert Mustacchi ctfsect.cts_data = cbuf; 825a386cc11SRobert Mustacchi ctfsect.cts_offset = 0; 826a386cc11SRobert Mustacchi ctp = &ctfsect; 827a386cc11SRobert Mustacchi 828a386cc11SRobert Mustacchi if (ofp->ctf_symtab.cts_data != NULL) { 829a386cc11SRobert Mustacchi bcopy(&ofp->ctf_symtab, &symsect, sizeof (ctf_sect_t)); 830a386cc11SRobert Mustacchi symbuf = ctf_data_alloc(symsect.cts_size); 831a386cc11SRobert Mustacchi if (symbuf == NULL) { 832a386cc11SRobert Mustacchi (void) ctf_set_errno(ofp, ECTF_MMAP); 833a386cc11SRobert Mustacchi goto err; 834a386cc11SRobert Mustacchi } 835a386cc11SRobert Mustacchi bcopy(symsect.cts_data, symbuf, symsect.cts_size); 836a386cc11SRobert Mustacchi ctf_data_protect(symbuf, symsect.cts_size); 837a386cc11SRobert Mustacchi symsect.cts_data = symbuf; 838a386cc11SRobert Mustacchi symsect.cts_offset = 0; 839a386cc11SRobert Mustacchi symp = &symsect; 840a386cc11SRobert Mustacchi } else { 841a386cc11SRobert Mustacchi symp = NULL; 842a386cc11SRobert Mustacchi } 843a386cc11SRobert Mustacchi 844a386cc11SRobert Mustacchi if (ofp->ctf_strtab.cts_data != NULL) { 845a386cc11SRobert Mustacchi bcopy(&ofp->ctf_strtab, &strsect, sizeof (ctf_sect_t)); 846a386cc11SRobert Mustacchi strbuf = ctf_data_alloc(strsect.cts_size); 847a386cc11SRobert Mustacchi if (strbuf == NULL) { 848a386cc11SRobert Mustacchi (void) ctf_set_errno(ofp, ECTF_MMAP); 849a386cc11SRobert Mustacchi goto err; 850a386cc11SRobert Mustacchi } 851a386cc11SRobert Mustacchi bcopy(strsect.cts_data, strbuf, strsect.cts_size); 852a386cc11SRobert Mustacchi ctf_data_protect(strbuf, strsect.cts_size); 853a386cc11SRobert Mustacchi strsect.cts_data = strbuf; 854a386cc11SRobert Mustacchi strsect.cts_offset = 0; 855a386cc11SRobert Mustacchi strp = &strsect; 856a386cc11SRobert Mustacchi } else { 857a386cc11SRobert Mustacchi strp = NULL; 858a386cc11SRobert Mustacchi } 859a386cc11SRobert Mustacchi 860a386cc11SRobert Mustacchi fp = ctf_bufopen(ctp, symp, strp, &err); 861a386cc11SRobert Mustacchi if (fp == NULL) { 862a386cc11SRobert Mustacchi (void) ctf_set_errno(ofp, err); 863a386cc11SRobert Mustacchi goto err; 864a386cc11SRobert Mustacchi } 865a386cc11SRobert Mustacchi 866a386cc11SRobert Mustacchi fp->ctf_flags |= LCTF_MMAP; 867a386cc11SRobert Mustacchi 868a386cc11SRobert Mustacchi return (fp); 869a386cc11SRobert Mustacchi 870a386cc11SRobert Mustacchi err: 871a386cc11SRobert Mustacchi ctf_data_free(cbuf, ctfsect.cts_size); 872a386cc11SRobert Mustacchi if (symbuf != NULL) 873a386cc11SRobert Mustacchi ctf_data_free(symbuf, symsect.cts_size); 874a386cc11SRobert Mustacchi if (strbuf != NULL) 875a386cc11SRobert Mustacchi ctf_data_free(strbuf, strsect.cts_size); 876a386cc11SRobert Mustacchi return (NULL); 877a386cc11SRobert Mustacchi } 878a386cc11SRobert Mustacchi 879a386cc11SRobert Mustacchi /* 8807c478bd9Sstevel@tonic-gate * Close the specified CTF container and free associated data structures. Note 8817c478bd9Sstevel@tonic-gate * that ctf_close() is a reference counted operation: if the specified file is 8827c478bd9Sstevel@tonic-gate * the parent of other active containers, its reference count will be greater 8837c478bd9Sstevel@tonic-gate * than one and it will be freed later when no active children exist. 8847c478bd9Sstevel@tonic-gate */ 8857c478bd9Sstevel@tonic-gate void 8867c478bd9Sstevel@tonic-gate ctf_close(ctf_file_t *fp) 8877c478bd9Sstevel@tonic-gate { 8887c478bd9Sstevel@tonic-gate ctf_dtdef_t *dtd, *ntd; 889*7fd79137SRobert Mustacchi ctf_dsdef_t *dsd, *nsd; 890*7fd79137SRobert Mustacchi ctf_dldef_t *dld, *nld; 8917c478bd9Sstevel@tonic-gate 8927c478bd9Sstevel@tonic-gate if (fp == NULL) 8937c478bd9Sstevel@tonic-gate return; /* allow ctf_close(NULL) to simplify caller code */ 8947c478bd9Sstevel@tonic-gate 8957c478bd9Sstevel@tonic-gate ctf_dprintf("ctf_close(%p) refcnt=%u\n", (void *)fp, fp->ctf_refcnt); 8967c478bd9Sstevel@tonic-gate 8977c478bd9Sstevel@tonic-gate if (fp->ctf_refcnt > 1) { 8987c478bd9Sstevel@tonic-gate fp->ctf_refcnt--; 8997c478bd9Sstevel@tonic-gate return; 9007c478bd9Sstevel@tonic-gate } 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate if (fp->ctf_parent != NULL) 9037c478bd9Sstevel@tonic-gate ctf_close(fp->ctf_parent); 9047c478bd9Sstevel@tonic-gate 9050a47c91cSRobert Mustacchi /* 9060a47c91cSRobert Mustacchi * Note, to work properly with reference counting on the dynamic 9070a47c91cSRobert Mustacchi * section, we must delete the list in reverse. 9080a47c91cSRobert Mustacchi */ 9090a47c91cSRobert Mustacchi for (dtd = ctf_list_prev(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) { 9100a47c91cSRobert Mustacchi ntd = ctf_list_prev(dtd); 911e4586ebfSmws ctf_dtd_delete(fp, dtd); 912e4586ebfSmws } 913e4586ebfSmws 914*7fd79137SRobert Mustacchi for (dsd = ctf_list_prev(&fp->ctf_dsdefs); dsd != NULL; dsd = nsd) { 915*7fd79137SRobert Mustacchi nsd = ctf_list_prev(dsd); 916*7fd79137SRobert Mustacchi ctf_dsd_delete(fp, dsd); 917*7fd79137SRobert Mustacchi } 918*7fd79137SRobert Mustacchi 919*7fd79137SRobert Mustacchi for (dld = ctf_list_prev(&fp->ctf_dldefs); dld != NULL; dld = nld) { 920*7fd79137SRobert Mustacchi nld = ctf_list_prev(dld); 921*7fd79137SRobert Mustacchi ctf_dld_delete(fp, dld); 922*7fd79137SRobert Mustacchi } 923*7fd79137SRobert Mustacchi 924e4586ebfSmws ctf_free(fp->ctf_dthash, fp->ctf_dthashlen * sizeof (ctf_dtdef_t *)); 925e4586ebfSmws 9267c478bd9Sstevel@tonic-gate if (fp->ctf_flags & LCTF_MMAP) { 927*7fd79137SRobert Mustacchi /* 928*7fd79137SRobert Mustacchi * Writeable containers shouldn't necessairily have the CTF 929*7fd79137SRobert Mustacchi * section freed. 930*7fd79137SRobert Mustacchi */ 931*7fd79137SRobert Mustacchi if (fp->ctf_data.cts_data != NULL && 932*7fd79137SRobert Mustacchi !(fp->ctf_flags & LCTF_RDWR)) 9337c478bd9Sstevel@tonic-gate ctf_sect_munmap(&fp->ctf_data); 9347c478bd9Sstevel@tonic-gate if (fp->ctf_symtab.cts_data != NULL) 9357c478bd9Sstevel@tonic-gate ctf_sect_munmap(&fp->ctf_symtab); 9367c478bd9Sstevel@tonic-gate if (fp->ctf_strtab.cts_data != NULL) 9377c478bd9Sstevel@tonic-gate ctf_sect_munmap(&fp->ctf_strtab); 9387c478bd9Sstevel@tonic-gate } 9397c478bd9Sstevel@tonic-gate 9407c478bd9Sstevel@tonic-gate if (fp->ctf_data.cts_name != _CTF_NULLSTR && 9417c478bd9Sstevel@tonic-gate fp->ctf_data.cts_name != NULL) { 9427c478bd9Sstevel@tonic-gate ctf_free((char *)fp->ctf_data.cts_name, 9437c478bd9Sstevel@tonic-gate strlen(fp->ctf_data.cts_name) + 1); 9447c478bd9Sstevel@tonic-gate } 9457c478bd9Sstevel@tonic-gate 9467c478bd9Sstevel@tonic-gate if (fp->ctf_symtab.cts_name != _CTF_NULLSTR && 9477c478bd9Sstevel@tonic-gate fp->ctf_symtab.cts_name != NULL) { 9487c478bd9Sstevel@tonic-gate ctf_free((char *)fp->ctf_symtab.cts_name, 9497c478bd9Sstevel@tonic-gate strlen(fp->ctf_symtab.cts_name) + 1); 9507c478bd9Sstevel@tonic-gate } 9517c478bd9Sstevel@tonic-gate 9527c478bd9Sstevel@tonic-gate if (fp->ctf_strtab.cts_name != _CTF_NULLSTR && 9537c478bd9Sstevel@tonic-gate fp->ctf_strtab.cts_name != NULL) { 9547c478bd9Sstevel@tonic-gate ctf_free((char *)fp->ctf_strtab.cts_name, 9557c478bd9Sstevel@tonic-gate strlen(fp->ctf_strtab.cts_name) + 1); 9567c478bd9Sstevel@tonic-gate } 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate if (fp->ctf_base != fp->ctf_data.cts_data && fp->ctf_base != NULL) 9597c478bd9Sstevel@tonic-gate ctf_data_free((void *)fp->ctf_base, fp->ctf_size); 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate if (fp->ctf_sxlate != NULL) 9627c478bd9Sstevel@tonic-gate ctf_free(fp->ctf_sxlate, sizeof (uint_t) * fp->ctf_nsyms); 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate if (fp->ctf_txlate != NULL) { 9657c478bd9Sstevel@tonic-gate ctf_free(fp->ctf_txlate, 9667c478bd9Sstevel@tonic-gate sizeof (uint_t) * (fp->ctf_typemax + 1)); 9677c478bd9Sstevel@tonic-gate } 9687c478bd9Sstevel@tonic-gate 9697c478bd9Sstevel@tonic-gate if (fp->ctf_ptrtab != NULL) { 9707c478bd9Sstevel@tonic-gate ctf_free(fp->ctf_ptrtab, 9717c478bd9Sstevel@tonic-gate sizeof (ushort_t) * (fp->ctf_typemax + 1)); 9727c478bd9Sstevel@tonic-gate } 9737c478bd9Sstevel@tonic-gate 9747c478bd9Sstevel@tonic-gate ctf_hash_destroy(&fp->ctf_structs); 9757c478bd9Sstevel@tonic-gate ctf_hash_destroy(&fp->ctf_unions); 9767c478bd9Sstevel@tonic-gate ctf_hash_destroy(&fp->ctf_enums); 9777c478bd9Sstevel@tonic-gate ctf_hash_destroy(&fp->ctf_names); 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate ctf_free(fp, sizeof (ctf_file_t)); 9807c478bd9Sstevel@tonic-gate } 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate /* 9837c478bd9Sstevel@tonic-gate * Return the CTF handle for the parent CTF container, if one exists. 9847c478bd9Sstevel@tonic-gate * Otherwise return NULL to indicate this container has no imported parent. 9857c478bd9Sstevel@tonic-gate */ 9867c478bd9Sstevel@tonic-gate ctf_file_t * 9877c478bd9Sstevel@tonic-gate ctf_parent_file(ctf_file_t *fp) 9887c478bd9Sstevel@tonic-gate { 9897c478bd9Sstevel@tonic-gate return (fp->ctf_parent); 9907c478bd9Sstevel@tonic-gate } 9917c478bd9Sstevel@tonic-gate 9927c478bd9Sstevel@tonic-gate /* 9937c478bd9Sstevel@tonic-gate * Return the name of the parent CTF container, if one exists. Otherwise 9947c478bd9Sstevel@tonic-gate * return NULL to indicate this container is a root container. 9957c478bd9Sstevel@tonic-gate */ 9967c478bd9Sstevel@tonic-gate const char * 9977c478bd9Sstevel@tonic-gate ctf_parent_name(ctf_file_t *fp) 9987c478bd9Sstevel@tonic-gate { 9997c478bd9Sstevel@tonic-gate return (fp->ctf_parname); 10007c478bd9Sstevel@tonic-gate } 10017c478bd9Sstevel@tonic-gate 10027c478bd9Sstevel@tonic-gate /* 1003*7fd79137SRobert Mustacchi * Return the label of the parent CTF container, if one exists. Otherwise return 1004*7fd79137SRobert Mustacchi * NULL. 1005*7fd79137SRobert Mustacchi */ 1006*7fd79137SRobert Mustacchi const char * 1007*7fd79137SRobert Mustacchi ctf_parent_label(ctf_file_t *fp) 1008*7fd79137SRobert Mustacchi { 1009*7fd79137SRobert Mustacchi return (fp->ctf_parlabel); 1010*7fd79137SRobert Mustacchi } 1011*7fd79137SRobert Mustacchi 1012*7fd79137SRobert Mustacchi /* 10137c478bd9Sstevel@tonic-gate * Import the types from the specified parent container by storing a pointer 10147c478bd9Sstevel@tonic-gate * to it in ctf_parent and incrementing its reference count. Only one parent 10157c478bd9Sstevel@tonic-gate * is allowed: if a parent already exists, it is replaced by the new parent. 10167c478bd9Sstevel@tonic-gate */ 10177c478bd9Sstevel@tonic-gate int 10187c478bd9Sstevel@tonic-gate ctf_import(ctf_file_t *fp, ctf_file_t *pfp) 10197c478bd9Sstevel@tonic-gate { 10207c478bd9Sstevel@tonic-gate if (fp == NULL || fp == pfp || (pfp != NULL && pfp->ctf_refcnt == 0)) 10217c478bd9Sstevel@tonic-gate return (ctf_set_errno(fp, EINVAL)); 10227c478bd9Sstevel@tonic-gate 10237c478bd9Sstevel@tonic-gate if (pfp != NULL && pfp->ctf_dmodel != fp->ctf_dmodel) 10247c478bd9Sstevel@tonic-gate return (ctf_set_errno(fp, ECTF_DMODEL)); 10257c478bd9Sstevel@tonic-gate 10267c478bd9Sstevel@tonic-gate if (fp->ctf_parent != NULL) 10277c478bd9Sstevel@tonic-gate ctf_close(fp->ctf_parent); 10287c478bd9Sstevel@tonic-gate 10297c478bd9Sstevel@tonic-gate if (pfp != NULL) { 10307c478bd9Sstevel@tonic-gate fp->ctf_flags |= LCTF_CHILD; 10317c478bd9Sstevel@tonic-gate pfp->ctf_refcnt++; 10327c478bd9Sstevel@tonic-gate } 10337c478bd9Sstevel@tonic-gate 10347c478bd9Sstevel@tonic-gate fp->ctf_parent = pfp; 10357c478bd9Sstevel@tonic-gate return (0); 10367c478bd9Sstevel@tonic-gate } 10377c478bd9Sstevel@tonic-gate 10387c478bd9Sstevel@tonic-gate /* 10397c478bd9Sstevel@tonic-gate * Set the data model constant for the CTF container. 10407c478bd9Sstevel@tonic-gate */ 10417c478bd9Sstevel@tonic-gate int 10427c478bd9Sstevel@tonic-gate ctf_setmodel(ctf_file_t *fp, int model) 10437c478bd9Sstevel@tonic-gate { 10447c478bd9Sstevel@tonic-gate const ctf_dmodel_t *dp; 10457c478bd9Sstevel@tonic-gate 10467c478bd9Sstevel@tonic-gate for (dp = _libctf_models; dp->ctd_name != NULL; dp++) { 10477c478bd9Sstevel@tonic-gate if (dp->ctd_code == model) { 10487c478bd9Sstevel@tonic-gate fp->ctf_dmodel = dp; 10497c478bd9Sstevel@tonic-gate return (0); 10507c478bd9Sstevel@tonic-gate } 10517c478bd9Sstevel@tonic-gate } 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate return (ctf_set_errno(fp, EINVAL)); 10547c478bd9Sstevel@tonic-gate } 10557c478bd9Sstevel@tonic-gate 10567c478bd9Sstevel@tonic-gate /* 10577c478bd9Sstevel@tonic-gate * Return the data model constant for the CTF container. 10587c478bd9Sstevel@tonic-gate */ 10597c478bd9Sstevel@tonic-gate int 10607c478bd9Sstevel@tonic-gate ctf_getmodel(ctf_file_t *fp) 10617c478bd9Sstevel@tonic-gate { 10627c478bd9Sstevel@tonic-gate return (fp->ctf_dmodel->ctd_code); 10637c478bd9Sstevel@tonic-gate } 10647c478bd9Sstevel@tonic-gate 10657c478bd9Sstevel@tonic-gate void 10667c478bd9Sstevel@tonic-gate ctf_setspecific(ctf_file_t *fp, void *data) 10677c478bd9Sstevel@tonic-gate { 10687c478bd9Sstevel@tonic-gate fp->ctf_specific = data; 10697c478bd9Sstevel@tonic-gate } 10707c478bd9Sstevel@tonic-gate 10717c478bd9Sstevel@tonic-gate void * 10727c478bd9Sstevel@tonic-gate ctf_getspecific(ctf_file_t *fp) 10737c478bd9Sstevel@tonic-gate { 10747c478bd9Sstevel@tonic-gate return (fp->ctf_specific); 10757c478bd9Sstevel@tonic-gate } 1076*7fd79137SRobert Mustacchi 1077*7fd79137SRobert Mustacchi uint_t 1078*7fd79137SRobert Mustacchi ctf_flags(ctf_file_t *fp) 1079*7fd79137SRobert Mustacchi { 1080*7fd79137SRobert Mustacchi return (fp->ctf_hflags); 1081*7fd79137SRobert Mustacchi } 1082