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 */ 22*e4586ebfSmws 237c478bd9Sstevel@tonic-gate /* 24*e4586ebfSmws * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <ctf_impl.h> 317c478bd9Sstevel@tonic-gate #include <sys/mman.h> 327c478bd9Sstevel@tonic-gate #include <sys/zmod.h> 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate static const ctf_dmodel_t _libctf_models[] = { 357c478bd9Sstevel@tonic-gate { "ILP32", CTF_MODEL_ILP32, 4, 1, 2, 4, 4 }, 367c478bd9Sstevel@tonic-gate { "LP64", CTF_MODEL_LP64, 8, 1, 2, 4, 8 }, 377c478bd9Sstevel@tonic-gate { NULL, 0, 0, 0, 0, 0, 0 } 387c478bd9Sstevel@tonic-gate }; 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate const char _CTF_SECTION[] = ".SUNW_ctf"; 417c478bd9Sstevel@tonic-gate const char _CTF_NULLSTR[] = ""; 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate int _libctf_version = CTF_VERSION; /* library client version */ 447c478bd9Sstevel@tonic-gate int _libctf_debug = 0; /* debugging messages enabled */ 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate static ushort_t 477c478bd9Sstevel@tonic-gate get_kind_v1(ushort_t info) 487c478bd9Sstevel@tonic-gate { 497c478bd9Sstevel@tonic-gate return (CTF_INFO_KIND_V1(info)); 507c478bd9Sstevel@tonic-gate } 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate static ushort_t 537c478bd9Sstevel@tonic-gate get_kind_v2(ushort_t info) 547c478bd9Sstevel@tonic-gate { 557c478bd9Sstevel@tonic-gate return (CTF_INFO_KIND(info)); 567c478bd9Sstevel@tonic-gate } 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate static ushort_t 597c478bd9Sstevel@tonic-gate get_root_v1(ushort_t info) 607c478bd9Sstevel@tonic-gate { 617c478bd9Sstevel@tonic-gate return (CTF_INFO_ISROOT_V1(info)); 627c478bd9Sstevel@tonic-gate } 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate static ushort_t 657c478bd9Sstevel@tonic-gate get_root_v2(ushort_t info) 667c478bd9Sstevel@tonic-gate { 677c478bd9Sstevel@tonic-gate return (CTF_INFO_ISROOT(info)); 687c478bd9Sstevel@tonic-gate } 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate static ushort_t 717c478bd9Sstevel@tonic-gate get_vlen_v1(ushort_t info) 727c478bd9Sstevel@tonic-gate { 737c478bd9Sstevel@tonic-gate return (CTF_INFO_VLEN_V1(info)); 747c478bd9Sstevel@tonic-gate } 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate static ushort_t 777c478bd9Sstevel@tonic-gate get_vlen_v2(ushort_t info) 787c478bd9Sstevel@tonic-gate { 797c478bd9Sstevel@tonic-gate return (CTF_INFO_VLEN(info)); 807c478bd9Sstevel@tonic-gate } 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate static const ctf_fileops_t ctf_fileops[] = { 837c478bd9Sstevel@tonic-gate { NULL, NULL }, 847c478bd9Sstevel@tonic-gate { get_kind_v1, get_root_v1, get_vlen_v1 }, 857c478bd9Sstevel@tonic-gate { get_kind_v2, get_root_v2, get_vlen_v2 }, 867c478bd9Sstevel@tonic-gate }; 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate /* 897c478bd9Sstevel@tonic-gate * Convert a 32-bit ELF symbol into GElf (Elf64) and return a pointer to it. 907c478bd9Sstevel@tonic-gate */ 917c478bd9Sstevel@tonic-gate static Elf64_Sym * 927c478bd9Sstevel@tonic-gate sym_to_gelf(const Elf32_Sym *src, Elf64_Sym *dst) 937c478bd9Sstevel@tonic-gate { 947c478bd9Sstevel@tonic-gate dst->st_name = src->st_name; 957c478bd9Sstevel@tonic-gate dst->st_value = src->st_value; 967c478bd9Sstevel@tonic-gate dst->st_size = src->st_size; 977c478bd9Sstevel@tonic-gate dst->st_info = src->st_info; 987c478bd9Sstevel@tonic-gate dst->st_other = src->st_other; 997c478bd9Sstevel@tonic-gate dst->st_shndx = src->st_shndx; 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate return (dst); 1027c478bd9Sstevel@tonic-gate } 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate /* 1057c478bd9Sstevel@tonic-gate * Initialize the symtab translation table by filling each entry with the 1067c478bd9Sstevel@tonic-gate * offset of the CTF type or function data corresponding to each STT_FUNC or 1077c478bd9Sstevel@tonic-gate * STT_OBJECT entry in the symbol table. 1087c478bd9Sstevel@tonic-gate */ 1097c478bd9Sstevel@tonic-gate static int 1107c478bd9Sstevel@tonic-gate init_symtab(ctf_file_t *fp, const ctf_header_t *hp, 1117c478bd9Sstevel@tonic-gate const ctf_sect_t *sp, const ctf_sect_t *strp) 1127c478bd9Sstevel@tonic-gate { 1137c478bd9Sstevel@tonic-gate const uchar_t *symp = sp->cts_data; 1147c478bd9Sstevel@tonic-gate uint_t *xp = fp->ctf_sxlate; 1157c478bd9Sstevel@tonic-gate uint_t *xend = xp + fp->ctf_nsyms; 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate uint_t objtoff = hp->cth_objtoff; 1187c478bd9Sstevel@tonic-gate uint_t funcoff = hp->cth_funcoff; 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate ushort_t info, vlen; 1217c478bd9Sstevel@tonic-gate Elf64_Sym sym, *gsp; 1227c478bd9Sstevel@tonic-gate const char *name; 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate /* 1257c478bd9Sstevel@tonic-gate * The CTF data object and function type sections are ordered to match 1267c478bd9Sstevel@tonic-gate * the relative order of the respective symbol types in the symtab. 1277c478bd9Sstevel@tonic-gate * If no type information is available for a symbol table entry, a 1287c478bd9Sstevel@tonic-gate * pad is inserted in the CTF section. As a further optimization, 1297c478bd9Sstevel@tonic-gate * anonymous or undefined symbols are omitted from the CTF data. 1307c478bd9Sstevel@tonic-gate */ 1317c478bd9Sstevel@tonic-gate for (; xp < xend; xp++, symp += sp->cts_entsize) { 1327c478bd9Sstevel@tonic-gate if (sp->cts_entsize == sizeof (Elf32_Sym)) 1337c478bd9Sstevel@tonic-gate gsp = sym_to_gelf((Elf32_Sym *)(uintptr_t)symp, &sym); 1347c478bd9Sstevel@tonic-gate else 1357c478bd9Sstevel@tonic-gate gsp = (Elf64_Sym *)(uintptr_t)symp; 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate if (gsp->st_name < strp->cts_size) 1387c478bd9Sstevel@tonic-gate name = (const char *)strp->cts_data + gsp->st_name; 1397c478bd9Sstevel@tonic-gate else 1407c478bd9Sstevel@tonic-gate name = _CTF_NULLSTR; 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate if (gsp->st_name == 0 || gsp->st_shndx == SHN_UNDEF || 1437c478bd9Sstevel@tonic-gate strcmp(name, "_START_") == 0 || 1447c478bd9Sstevel@tonic-gate strcmp(name, "_END_") == 0) { 1457c478bd9Sstevel@tonic-gate *xp = -1u; 1467c478bd9Sstevel@tonic-gate continue; 1477c478bd9Sstevel@tonic-gate } 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate switch (ELF64_ST_TYPE(gsp->st_info)) { 1507c478bd9Sstevel@tonic-gate case STT_OBJECT: 1517c478bd9Sstevel@tonic-gate if (objtoff >= hp->cth_funcoff || 1527c478bd9Sstevel@tonic-gate (gsp->st_shndx == SHN_ABS && gsp->st_value == 0)) { 1537c478bd9Sstevel@tonic-gate *xp = -1u; 1547c478bd9Sstevel@tonic-gate break; 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate *xp = objtoff; 1587c478bd9Sstevel@tonic-gate objtoff += sizeof (ushort_t); 1597c478bd9Sstevel@tonic-gate break; 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate case STT_FUNC: 1627c478bd9Sstevel@tonic-gate if (funcoff >= hp->cth_typeoff) { 1637c478bd9Sstevel@tonic-gate *xp = -1u; 1647c478bd9Sstevel@tonic-gate break; 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate *xp = funcoff; 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate info = *(ushort_t *)((uintptr_t)fp->ctf_buf + funcoff); 1707c478bd9Sstevel@tonic-gate vlen = LCTF_INFO_VLEN(fp, info); 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate /* 1737c478bd9Sstevel@tonic-gate * If we encounter a zero pad at the end, just skip it. 1747c478bd9Sstevel@tonic-gate * Otherwise skip over the function and its return type 1757c478bd9Sstevel@tonic-gate * (+2) and the argument list (vlen). 1767c478bd9Sstevel@tonic-gate */ 1777c478bd9Sstevel@tonic-gate if (LCTF_INFO_KIND(fp, info) == CTF_K_UNKNOWN && 1787c478bd9Sstevel@tonic-gate vlen == 0) 1797c478bd9Sstevel@tonic-gate funcoff += sizeof (ushort_t); /* skip pad */ 1807c478bd9Sstevel@tonic-gate else 1817c478bd9Sstevel@tonic-gate funcoff += sizeof (ushort_t) * (vlen + 2); 1827c478bd9Sstevel@tonic-gate break; 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate default: 1857c478bd9Sstevel@tonic-gate *xp = -1u; 1867c478bd9Sstevel@tonic-gate break; 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate } 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate ctf_dprintf("loaded %lu symtab entries\n", fp->ctf_nsyms); 1917c478bd9Sstevel@tonic-gate return (0); 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate /* 1957c478bd9Sstevel@tonic-gate * Initialize the type ID translation table with the byte offset of each type, 1967c478bd9Sstevel@tonic-gate * and initialize the hash tables of each named type. 1977c478bd9Sstevel@tonic-gate */ 1987c478bd9Sstevel@tonic-gate static int 199*e4586ebfSmws init_types(ctf_file_t *fp, const ctf_header_t *cth) 2007c478bd9Sstevel@tonic-gate { 2017c478bd9Sstevel@tonic-gate /* LINTED - pointer alignment */ 202*e4586ebfSmws const ctf_type_t *tbuf = (ctf_type_t *)(fp->ctf_buf + cth->cth_typeoff); 2037c478bd9Sstevel@tonic-gate /* LINTED - pointer alignment */ 204*e4586ebfSmws const ctf_type_t *tend = (ctf_type_t *)(fp->ctf_buf + cth->cth_stroff); 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate ulong_t pop[CTF_K_MAX + 1] = { 0 }; 2077c478bd9Sstevel@tonic-gate const ctf_type_t *tp; 208*e4586ebfSmws ctf_hash_t *hp; 2097c478bd9Sstevel@tonic-gate ushort_t id, dst; 2107c478bd9Sstevel@tonic-gate uint_t *xp; 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate /* 2137c478bd9Sstevel@tonic-gate * We initially determine whether the container is a child or a parent 2147c478bd9Sstevel@tonic-gate * based on the value of cth_parname. To support containers that pre- 2157c478bd9Sstevel@tonic-gate * date cth_parname, we also scan the types themselves for references 2167c478bd9Sstevel@tonic-gate * to values in the range reserved for child types in our first pass. 2177c478bd9Sstevel@tonic-gate */ 218*e4586ebfSmws int child = cth->cth_parname != 0; 2197c478bd9Sstevel@tonic-gate int nlstructs = 0, nlunions = 0; 2207c478bd9Sstevel@tonic-gate int err; 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate /* 2237c478bd9Sstevel@tonic-gate * We make two passes through the entire type section. In this first 2247c478bd9Sstevel@tonic-gate * pass, we count the number of each type and the total number of types. 2257c478bd9Sstevel@tonic-gate */ 2267c478bd9Sstevel@tonic-gate for (tp = tbuf; tp < tend; fp->ctf_typemax++) { 2277c478bd9Sstevel@tonic-gate ushort_t kind = LCTF_INFO_KIND(fp, tp->ctt_info); 2287c478bd9Sstevel@tonic-gate ulong_t vlen = LCTF_INFO_VLEN(fp, tp->ctt_info); 2297c478bd9Sstevel@tonic-gate ssize_t size, increment; 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate size_t vbytes; 2327c478bd9Sstevel@tonic-gate uint_t n; 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate (void) ctf_get_ctt_size(fp, tp, &size, &increment); 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate switch (kind) { 2377c478bd9Sstevel@tonic-gate case CTF_K_INTEGER: 2387c478bd9Sstevel@tonic-gate case CTF_K_FLOAT: 2397c478bd9Sstevel@tonic-gate vbytes = sizeof (uint_t); 2407c478bd9Sstevel@tonic-gate break; 2417c478bd9Sstevel@tonic-gate case CTF_K_ARRAY: 2427c478bd9Sstevel@tonic-gate vbytes = sizeof (ctf_array_t); 2437c478bd9Sstevel@tonic-gate break; 2447c478bd9Sstevel@tonic-gate case CTF_K_FUNCTION: 2457c478bd9Sstevel@tonic-gate vbytes = sizeof (ushort_t) * (vlen + (vlen & 1)); 2467c478bd9Sstevel@tonic-gate break; 2477c478bd9Sstevel@tonic-gate case CTF_K_STRUCT: 2487c478bd9Sstevel@tonic-gate case CTF_K_UNION: 2497c478bd9Sstevel@tonic-gate if (fp->ctf_version == CTF_VERSION_1 || 2507c478bd9Sstevel@tonic-gate size < CTF_LSTRUCT_THRESH) { 2517c478bd9Sstevel@tonic-gate ctf_member_t *mp = (ctf_member_t *) 2527c478bd9Sstevel@tonic-gate ((uintptr_t)tp + increment); 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate vbytes = sizeof (ctf_member_t) * vlen; 2557c478bd9Sstevel@tonic-gate for (n = vlen; n != 0; n--, mp++) 2567c478bd9Sstevel@tonic-gate child |= CTF_TYPE_ISCHILD(mp->ctm_type); 2577c478bd9Sstevel@tonic-gate } else { 2587c478bd9Sstevel@tonic-gate ctf_lmember_t *lmp = (ctf_lmember_t *) 2597c478bd9Sstevel@tonic-gate ((uintptr_t)tp + increment); 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate vbytes = sizeof (ctf_lmember_t) * vlen; 2627c478bd9Sstevel@tonic-gate for (n = vlen; n != 0; n--, lmp++) 2637c478bd9Sstevel@tonic-gate child |= 2647c478bd9Sstevel@tonic-gate CTF_TYPE_ISCHILD(lmp->ctlm_type); 2657c478bd9Sstevel@tonic-gate } 2667c478bd9Sstevel@tonic-gate break; 2677c478bd9Sstevel@tonic-gate case CTF_K_ENUM: 2687c478bd9Sstevel@tonic-gate vbytes = sizeof (ctf_enum_t) * vlen; 2697c478bd9Sstevel@tonic-gate break; 2707c478bd9Sstevel@tonic-gate case CTF_K_FORWARD: 271*e4586ebfSmws /* 272*e4586ebfSmws * For forward declarations, ctt_type is the CTF_K_* 273*e4586ebfSmws * kind for the tag, so bump that population count too. 274*e4586ebfSmws * If ctt_type is unknown, treat the tag as a struct. 275*e4586ebfSmws */ 276*e4586ebfSmws if (tp->ctt_type == CTF_K_UNKNOWN || 277*e4586ebfSmws tp->ctt_type >= CTF_K_MAX) 278*e4586ebfSmws pop[CTF_K_STRUCT]++; 279*e4586ebfSmws else 280*e4586ebfSmws pop[tp->ctt_type]++; 281*e4586ebfSmws /*FALLTHRU*/ 2827c478bd9Sstevel@tonic-gate case CTF_K_UNKNOWN: 2837c478bd9Sstevel@tonic-gate vbytes = 0; 2847c478bd9Sstevel@tonic-gate break; 2857c478bd9Sstevel@tonic-gate case CTF_K_POINTER: 2867c478bd9Sstevel@tonic-gate case CTF_K_TYPEDEF: 2877c478bd9Sstevel@tonic-gate case CTF_K_VOLATILE: 2887c478bd9Sstevel@tonic-gate case CTF_K_CONST: 2897c478bd9Sstevel@tonic-gate case CTF_K_RESTRICT: 2907c478bd9Sstevel@tonic-gate child |= CTF_TYPE_ISCHILD(tp->ctt_type); 2917c478bd9Sstevel@tonic-gate vbytes = 0; 2927c478bd9Sstevel@tonic-gate break; 2937c478bd9Sstevel@tonic-gate default: 2947c478bd9Sstevel@tonic-gate ctf_dprintf("detected invalid CTF kind -- %u\n", kind); 2957c478bd9Sstevel@tonic-gate return (ECTF_CORRUPT); 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes); 2987c478bd9Sstevel@tonic-gate pop[kind]++; 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate /* 3027c478bd9Sstevel@tonic-gate * If we detected a reference to a child type ID, then we know this 3037c478bd9Sstevel@tonic-gate * container is a child and may have a parent's types imported later. 3047c478bd9Sstevel@tonic-gate */ 3057c478bd9Sstevel@tonic-gate if (child) { 3067c478bd9Sstevel@tonic-gate ctf_dprintf("CTF container %p is a child\n", (void *)fp); 3077c478bd9Sstevel@tonic-gate fp->ctf_flags |= LCTF_CHILD; 3087c478bd9Sstevel@tonic-gate } else 3097c478bd9Sstevel@tonic-gate ctf_dprintf("CTF container %p is a parent\n", (void *)fp); 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate /* 3127c478bd9Sstevel@tonic-gate * Now that we've counted up the number of each type, we can allocate 3137c478bd9Sstevel@tonic-gate * the hash tables, type translation table, and pointer table. 3147c478bd9Sstevel@tonic-gate */ 315*e4586ebfSmws if ((err = ctf_hash_create(&fp->ctf_structs, pop[CTF_K_STRUCT])) != 0) 3167c478bd9Sstevel@tonic-gate return (err); 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate if ((err = ctf_hash_create(&fp->ctf_unions, pop[CTF_K_UNION])) != 0) 3197c478bd9Sstevel@tonic-gate return (err); 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate if ((err = ctf_hash_create(&fp->ctf_enums, pop[CTF_K_ENUM])) != 0) 3227c478bd9Sstevel@tonic-gate return (err); 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate if ((err = ctf_hash_create(&fp->ctf_names, 3257c478bd9Sstevel@tonic-gate pop[CTF_K_INTEGER] + pop[CTF_K_FLOAT] + pop[CTF_K_FUNCTION] + 3267c478bd9Sstevel@tonic-gate pop[CTF_K_TYPEDEF] + pop[CTF_K_POINTER] + pop[CTF_K_VOLATILE] + 3277c478bd9Sstevel@tonic-gate pop[CTF_K_CONST] + pop[CTF_K_RESTRICT])) != 0) 3287c478bd9Sstevel@tonic-gate return (err); 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate fp->ctf_txlate = ctf_alloc(sizeof (uint_t) * (fp->ctf_typemax + 1)); 3317c478bd9Sstevel@tonic-gate fp->ctf_ptrtab = ctf_alloc(sizeof (ushort_t) * (fp->ctf_typemax + 1)); 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate if (fp->ctf_txlate == NULL || fp->ctf_ptrtab == NULL) 3347c478bd9Sstevel@tonic-gate return (EAGAIN); /* memory allocation failed */ 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate xp = fp->ctf_txlate; 3377c478bd9Sstevel@tonic-gate *xp++ = 0; /* type id 0 is used as a sentinel value */ 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate bzero(fp->ctf_txlate, sizeof (uint_t) * (fp->ctf_typemax + 1)); 3407c478bd9Sstevel@tonic-gate bzero(fp->ctf_ptrtab, sizeof (ushort_t) * (fp->ctf_typemax + 1)); 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate /* 3437c478bd9Sstevel@tonic-gate * In the second pass through the types, we fill in each entry of the 3447c478bd9Sstevel@tonic-gate * type and pointer tables and add names to the appropriate hashes. 3457c478bd9Sstevel@tonic-gate */ 3467c478bd9Sstevel@tonic-gate for (id = 1, tp = tbuf; tp < tend; xp++, id++) { 3477c478bd9Sstevel@tonic-gate ushort_t kind = LCTF_INFO_KIND(fp, tp->ctt_info); 3487c478bd9Sstevel@tonic-gate ulong_t vlen = LCTF_INFO_VLEN(fp, tp->ctt_info); 3497c478bd9Sstevel@tonic-gate ssize_t size, increment; 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate const char *name; 3527c478bd9Sstevel@tonic-gate size_t vbytes; 3537c478bd9Sstevel@tonic-gate ctf_helem_t *hep; 3547c478bd9Sstevel@tonic-gate ctf_encoding_t cte; 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate (void) ctf_get_ctt_size(fp, tp, &size, &increment); 3577c478bd9Sstevel@tonic-gate name = ctf_strptr(fp, tp->ctt_name); 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate switch (kind) { 3607c478bd9Sstevel@tonic-gate case CTF_K_INTEGER: 3617c478bd9Sstevel@tonic-gate case CTF_K_FLOAT: 3627c478bd9Sstevel@tonic-gate /* 3637c478bd9Sstevel@tonic-gate * Only insert a new integer base type definition if 3647c478bd9Sstevel@tonic-gate * this type name has not been defined yet. We re-use 3657c478bd9Sstevel@tonic-gate * the names with different encodings for bit-fields. 3667c478bd9Sstevel@tonic-gate */ 3677c478bd9Sstevel@tonic-gate if ((hep = ctf_hash_lookup(&fp->ctf_names, fp, 3687c478bd9Sstevel@tonic-gate name, strlen(name))) == NULL) { 3697c478bd9Sstevel@tonic-gate err = ctf_hash_insert(&fp->ctf_names, fp, 3707c478bd9Sstevel@tonic-gate CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 3717c478bd9Sstevel@tonic-gate if (err != 0 && err != ECTF_STRTAB) 3727c478bd9Sstevel@tonic-gate return (err); 3737c478bd9Sstevel@tonic-gate } else if (ctf_type_encoding(fp, hep->h_type, 3747c478bd9Sstevel@tonic-gate &cte) == 0 && cte.cte_bits == 0) { 3757c478bd9Sstevel@tonic-gate /* 3767c478bd9Sstevel@tonic-gate * Work-around SOS8 stabs bug: replace existing 3777c478bd9Sstevel@tonic-gate * intrinsic w/ same name if it was zero bits. 3787c478bd9Sstevel@tonic-gate */ 3797c478bd9Sstevel@tonic-gate hep->h_type = CTF_INDEX_TO_TYPE(id, child); 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate vbytes = sizeof (uint_t); 3827c478bd9Sstevel@tonic-gate break; 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate case CTF_K_ARRAY: 3857c478bd9Sstevel@tonic-gate vbytes = sizeof (ctf_array_t); 3867c478bd9Sstevel@tonic-gate break; 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate case CTF_K_FUNCTION: 3897c478bd9Sstevel@tonic-gate err = ctf_hash_insert(&fp->ctf_names, fp, 3907c478bd9Sstevel@tonic-gate CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 3917c478bd9Sstevel@tonic-gate if (err != 0 && err != ECTF_STRTAB) 3927c478bd9Sstevel@tonic-gate return (err); 3937c478bd9Sstevel@tonic-gate vbytes = sizeof (ushort_t) * (vlen + (vlen & 1)); 3947c478bd9Sstevel@tonic-gate break; 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate case CTF_K_STRUCT: 397*e4586ebfSmws err = ctf_hash_define(&fp->ctf_structs, fp, 3987c478bd9Sstevel@tonic-gate CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 399*e4586ebfSmws 4007c478bd9Sstevel@tonic-gate if (err != 0 && err != ECTF_STRTAB) 4017c478bd9Sstevel@tonic-gate return (err); 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate if (fp->ctf_version == CTF_VERSION_1 || 4047c478bd9Sstevel@tonic-gate size < CTF_LSTRUCT_THRESH) 4057c478bd9Sstevel@tonic-gate vbytes = sizeof (ctf_member_t) * vlen; 4067c478bd9Sstevel@tonic-gate else { 4077c478bd9Sstevel@tonic-gate vbytes = sizeof (ctf_lmember_t) * vlen; 4087c478bd9Sstevel@tonic-gate nlstructs++; 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate break; 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate case CTF_K_UNION: 413*e4586ebfSmws err = ctf_hash_define(&fp->ctf_unions, fp, 4147c478bd9Sstevel@tonic-gate CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 415*e4586ebfSmws 4167c478bd9Sstevel@tonic-gate if (err != 0 && err != ECTF_STRTAB) 4177c478bd9Sstevel@tonic-gate return (err); 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate if (fp->ctf_version == CTF_VERSION_1 || 4207c478bd9Sstevel@tonic-gate size < CTF_LSTRUCT_THRESH) 4217c478bd9Sstevel@tonic-gate vbytes = sizeof (ctf_member_t) * vlen; 4227c478bd9Sstevel@tonic-gate else { 4237c478bd9Sstevel@tonic-gate vbytes = sizeof (ctf_lmember_t) * vlen; 4247c478bd9Sstevel@tonic-gate nlunions++; 4257c478bd9Sstevel@tonic-gate } 4267c478bd9Sstevel@tonic-gate break; 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate case CTF_K_ENUM: 429*e4586ebfSmws err = ctf_hash_define(&fp->ctf_enums, fp, 4307c478bd9Sstevel@tonic-gate CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 431*e4586ebfSmws 4327c478bd9Sstevel@tonic-gate if (err != 0 && err != ECTF_STRTAB) 4337c478bd9Sstevel@tonic-gate return (err); 434*e4586ebfSmws 4357c478bd9Sstevel@tonic-gate vbytes = sizeof (ctf_enum_t) * vlen; 4367c478bd9Sstevel@tonic-gate break; 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate case CTF_K_TYPEDEF: 4397c478bd9Sstevel@tonic-gate err = ctf_hash_insert(&fp->ctf_names, fp, 4407c478bd9Sstevel@tonic-gate CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 4417c478bd9Sstevel@tonic-gate if (err != 0 && err != ECTF_STRTAB) 4427c478bd9Sstevel@tonic-gate return (err); 4437c478bd9Sstevel@tonic-gate vbytes = 0; 4447c478bd9Sstevel@tonic-gate break; 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate case CTF_K_FORWARD: 4477c478bd9Sstevel@tonic-gate /* 448*e4586ebfSmws * Only insert forward tags into the given hash if the 449*e4586ebfSmws * type or tag name is not already present. 4507c478bd9Sstevel@tonic-gate */ 451*e4586ebfSmws switch (tp->ctt_type) { 452*e4586ebfSmws case CTF_K_STRUCT: 453*e4586ebfSmws hp = &fp->ctf_structs; 454*e4586ebfSmws break; 455*e4586ebfSmws case CTF_K_UNION: 456*e4586ebfSmws hp = &fp->ctf_unions; 457*e4586ebfSmws break; 458*e4586ebfSmws case CTF_K_ENUM: 459*e4586ebfSmws hp = &fp->ctf_enums; 460*e4586ebfSmws break; 461*e4586ebfSmws default: 462*e4586ebfSmws hp = &fp->ctf_structs; 463*e4586ebfSmws } 464*e4586ebfSmws 465*e4586ebfSmws if (ctf_hash_lookup(hp, fp, 4667c478bd9Sstevel@tonic-gate name, strlen(name)) == NULL) { 467*e4586ebfSmws err = ctf_hash_insert(hp, fp, 4687c478bd9Sstevel@tonic-gate CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 4697c478bd9Sstevel@tonic-gate if (err != 0 && err != ECTF_STRTAB) 4707c478bd9Sstevel@tonic-gate return (err); 4717c478bd9Sstevel@tonic-gate } 4727c478bd9Sstevel@tonic-gate vbytes = 0; 4737c478bd9Sstevel@tonic-gate break; 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate case CTF_K_POINTER: 4767c478bd9Sstevel@tonic-gate /* 4777c478bd9Sstevel@tonic-gate * If the type referenced by the pointer is in this CTF 4787c478bd9Sstevel@tonic-gate * container, then store the index of the pointer type 4797c478bd9Sstevel@tonic-gate * in fp->ctf_ptrtab[ index of referenced type ]. 4807c478bd9Sstevel@tonic-gate */ 4817c478bd9Sstevel@tonic-gate if (CTF_TYPE_ISCHILD(tp->ctt_type) == child && 4827c478bd9Sstevel@tonic-gate CTF_TYPE_TO_INDEX(tp->ctt_type) <= fp->ctf_typemax) 4837c478bd9Sstevel@tonic-gate fp->ctf_ptrtab[ 4847c478bd9Sstevel@tonic-gate CTF_TYPE_TO_INDEX(tp->ctt_type)] = id; 4857c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate case CTF_K_VOLATILE: 4887c478bd9Sstevel@tonic-gate case CTF_K_CONST: 4897c478bd9Sstevel@tonic-gate case CTF_K_RESTRICT: 4907c478bd9Sstevel@tonic-gate err = ctf_hash_insert(&fp->ctf_names, fp, 4917c478bd9Sstevel@tonic-gate CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 4927c478bd9Sstevel@tonic-gate if (err != 0 && err != ECTF_STRTAB) 4937c478bd9Sstevel@tonic-gate return (err); 4947c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate default: 4977c478bd9Sstevel@tonic-gate vbytes = 0; 4987c478bd9Sstevel@tonic-gate break; 4997c478bd9Sstevel@tonic-gate } 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate *xp = (uint_t)((uintptr_t)tp - (uintptr_t)fp->ctf_buf); 5027c478bd9Sstevel@tonic-gate tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes); 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate ctf_dprintf("%lu total types processed\n", fp->ctf_typemax); 5067c478bd9Sstevel@tonic-gate ctf_dprintf("%u enum names hashed\n", ctf_hash_size(&fp->ctf_enums)); 5077c478bd9Sstevel@tonic-gate ctf_dprintf("%u struct names hashed (%d long)\n", 5087c478bd9Sstevel@tonic-gate ctf_hash_size(&fp->ctf_structs), nlstructs); 5097c478bd9Sstevel@tonic-gate ctf_dprintf("%u union names hashed (%d long)\n", 5107c478bd9Sstevel@tonic-gate ctf_hash_size(&fp->ctf_unions), nlunions); 5117c478bd9Sstevel@tonic-gate ctf_dprintf("%u base type names hashed\n", 5127c478bd9Sstevel@tonic-gate ctf_hash_size(&fp->ctf_names)); 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate /* 5157c478bd9Sstevel@tonic-gate * Make an additional pass through the pointer table to find pointers 5167c478bd9Sstevel@tonic-gate * that point to anonymous typedef nodes. If we find one, modify the 5177c478bd9Sstevel@tonic-gate * pointer table so that the pointer is also known to point to the 5187c478bd9Sstevel@tonic-gate * node that is referenced by the anonymous typedef node. 5197c478bd9Sstevel@tonic-gate */ 5207c478bd9Sstevel@tonic-gate for (id = 1; id <= fp->ctf_typemax; id++) { 5217c478bd9Sstevel@tonic-gate if ((dst = fp->ctf_ptrtab[id]) != 0) { 5227c478bd9Sstevel@tonic-gate tp = LCTF_INDEX_TO_TYPEPTR(fp, id); 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate if (LCTF_INFO_KIND(fp, tp->ctt_info) == CTF_K_TYPEDEF && 5257c478bd9Sstevel@tonic-gate strcmp(ctf_strptr(fp, tp->ctt_name), "") == 0 && 5267c478bd9Sstevel@tonic-gate CTF_TYPE_ISCHILD(tp->ctt_type) == child && 5277c478bd9Sstevel@tonic-gate CTF_TYPE_TO_INDEX(tp->ctt_type) <= fp->ctf_typemax) 5287c478bd9Sstevel@tonic-gate fp->ctf_ptrtab[ 5297c478bd9Sstevel@tonic-gate CTF_TYPE_TO_INDEX(tp->ctt_type)] = dst; 5307c478bd9Sstevel@tonic-gate } 5317c478bd9Sstevel@tonic-gate } 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate return (0); 5347c478bd9Sstevel@tonic-gate } 5357c478bd9Sstevel@tonic-gate 5367c478bd9Sstevel@tonic-gate /* 5377c478bd9Sstevel@tonic-gate * Decode the specified CTF buffer and optional symbol table and create a new 5387c478bd9Sstevel@tonic-gate * CTF container representing the symbolic debugging information. This code 5397c478bd9Sstevel@tonic-gate * can be used directly by the debugger, or it can be used as the engine for 5407c478bd9Sstevel@tonic-gate * ctf_fdopen() or ctf_open(), below. 5417c478bd9Sstevel@tonic-gate */ 5427c478bd9Sstevel@tonic-gate ctf_file_t * 5437c478bd9Sstevel@tonic-gate ctf_bufopen(const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, 5447c478bd9Sstevel@tonic-gate const ctf_sect_t *strsect, int *errp) 5457c478bd9Sstevel@tonic-gate { 5467c478bd9Sstevel@tonic-gate const ctf_preamble_t *pp; 5477c478bd9Sstevel@tonic-gate ctf_header_t hp; 5487c478bd9Sstevel@tonic-gate ctf_file_t *fp; 5497c478bd9Sstevel@tonic-gate void *buf, *base; 5507c478bd9Sstevel@tonic-gate size_t size, hdrsz; 5517c478bd9Sstevel@tonic-gate int err; 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate if (ctfsect == NULL || ((symsect == NULL) != (strsect == NULL))) 5547c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, EINVAL)); 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate if (symsect != NULL && symsect->cts_entsize != sizeof (Elf32_Sym) && 5577c478bd9Sstevel@tonic-gate symsect->cts_entsize != sizeof (Elf64_Sym)) 5587c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_SYMTAB)); 5597c478bd9Sstevel@tonic-gate 5607c478bd9Sstevel@tonic-gate if (symsect != NULL && symsect->cts_data == NULL) 5617c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_SYMBAD)); 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate if (strsect != NULL && strsect->cts_data == NULL) 5647c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_STRBAD)); 5657c478bd9Sstevel@tonic-gate 5667c478bd9Sstevel@tonic-gate if (ctfsect->cts_size < sizeof (ctf_preamble_t)) 5677c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_NOCTFBUF)); 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate pp = (const ctf_preamble_t *)ctfsect->cts_data; 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate ctf_dprintf("ctf_bufopen: magic=0x%x version=%u\n", 5727c478bd9Sstevel@tonic-gate pp->ctp_magic, pp->ctp_version); 5737c478bd9Sstevel@tonic-gate 5747c478bd9Sstevel@tonic-gate /* 5757c478bd9Sstevel@tonic-gate * Validate each part of the CTF header (either V1 or V2). 5767c478bd9Sstevel@tonic-gate * First, we validate the preamble (common to all versions). At that 5777c478bd9Sstevel@tonic-gate * point, we know specific header version, and can validate the 5787c478bd9Sstevel@tonic-gate * version-specific parts including section offsets and alignments. 5797c478bd9Sstevel@tonic-gate */ 5807c478bd9Sstevel@tonic-gate if (pp->ctp_magic != CTF_MAGIC) 5817c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_NOCTFBUF)); 5827c478bd9Sstevel@tonic-gate 5837c478bd9Sstevel@tonic-gate if (pp->ctp_version == CTF_VERSION_2) { 5847c478bd9Sstevel@tonic-gate if (ctfsect->cts_size < sizeof (ctf_header_t)) 5857c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_NOCTFBUF)); 5867c478bd9Sstevel@tonic-gate 5877c478bd9Sstevel@tonic-gate bcopy(ctfsect->cts_data, &hp, sizeof (hp)); 5887c478bd9Sstevel@tonic-gate hdrsz = sizeof (ctf_header_t); 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate } else if (pp->ctp_version == CTF_VERSION_1) { 5917c478bd9Sstevel@tonic-gate const ctf_header_v1_t *h1p = 5927c478bd9Sstevel@tonic-gate (const ctf_header_v1_t *)ctfsect->cts_data; 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate if (ctfsect->cts_size < sizeof (ctf_header_v1_t)) 5957c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_NOCTFBUF)); 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate bzero(&hp, sizeof (hp)); 5987c478bd9Sstevel@tonic-gate hp.cth_preamble = h1p->cth_preamble; 5997c478bd9Sstevel@tonic-gate hp.cth_objtoff = h1p->cth_objtoff; 6007c478bd9Sstevel@tonic-gate hp.cth_funcoff = h1p->cth_funcoff; 6017c478bd9Sstevel@tonic-gate hp.cth_typeoff = h1p->cth_typeoff; 6027c478bd9Sstevel@tonic-gate hp.cth_stroff = h1p->cth_stroff; 6037c478bd9Sstevel@tonic-gate hp.cth_strlen = h1p->cth_strlen; 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate hdrsz = sizeof (ctf_header_v1_t); 6067c478bd9Sstevel@tonic-gate } else 6077c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_CTFVERS)); 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate size = hp.cth_stroff + hp.cth_strlen; 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate ctf_dprintf("ctf_bufopen: uncompressed size=%lu\n", (ulong_t)size); 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate if (hp.cth_lbloff > size || hp.cth_objtoff > size || 6147c478bd9Sstevel@tonic-gate hp.cth_funcoff > size || hp.cth_typeoff > size || 6157c478bd9Sstevel@tonic-gate hp.cth_stroff > size) 6167c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_CORRUPT)); 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate if (hp.cth_lbloff > hp.cth_objtoff || 6197c478bd9Sstevel@tonic-gate hp.cth_objtoff > hp.cth_funcoff || 6207c478bd9Sstevel@tonic-gate hp.cth_funcoff > hp.cth_typeoff || 6217c478bd9Sstevel@tonic-gate hp.cth_typeoff > hp.cth_stroff) 6227c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_CORRUPT)); 6237c478bd9Sstevel@tonic-gate 6247c478bd9Sstevel@tonic-gate if ((hp.cth_lbloff & 3) || (hp.cth_objtoff & 1) || 6257c478bd9Sstevel@tonic-gate (hp.cth_funcoff & 1) || (hp.cth_typeoff & 3)) 6267c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_CORRUPT)); 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate /* 6297c478bd9Sstevel@tonic-gate * Once everything is determined to be valid, attempt to decompress 6307c478bd9Sstevel@tonic-gate * the CTF data buffer if it is compressed. Otherwise we just put 6317c478bd9Sstevel@tonic-gate * the data section's buffer pointer into ctf_buf, below. 6327c478bd9Sstevel@tonic-gate */ 6337c478bd9Sstevel@tonic-gate if (hp.cth_flags & CTF_F_COMPRESS) { 6347c478bd9Sstevel@tonic-gate size_t srclen, dstlen; 6357c478bd9Sstevel@tonic-gate const void *src; 6367c478bd9Sstevel@tonic-gate int rc = Z_OK; 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate if (ctf_zopen(errp) == NULL) 6397c478bd9Sstevel@tonic-gate return (NULL); /* errp is set for us */ 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate if ((base = ctf_data_alloc(size + hdrsz)) == MAP_FAILED) 6427c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_ZALLOC)); 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate bcopy(ctfsect->cts_data, base, hdrsz); 6457c478bd9Sstevel@tonic-gate ((ctf_preamble_t *)base)->ctp_flags &= ~CTF_F_COMPRESS; 6467c478bd9Sstevel@tonic-gate buf = (uchar_t *)base + hdrsz; 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate src = (uchar_t *)ctfsect->cts_data + hdrsz; 6497c478bd9Sstevel@tonic-gate srclen = ctfsect->cts_size - hdrsz; 6507c478bd9Sstevel@tonic-gate dstlen = size; 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate if ((rc = z_uncompress(buf, &dstlen, src, srclen)) != Z_OK) { 6537c478bd9Sstevel@tonic-gate ctf_dprintf("zlib inflate err: %s\n", z_strerror(rc)); 6547c478bd9Sstevel@tonic-gate ctf_data_free(base, size + hdrsz); 6557c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_DECOMPRESS)); 6567c478bd9Sstevel@tonic-gate } 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate if (dstlen != size) { 6597c478bd9Sstevel@tonic-gate ctf_dprintf("zlib inflate short -- got %lu of %lu " 6607c478bd9Sstevel@tonic-gate "bytes\n", (ulong_t)dstlen, (ulong_t)size); 6617c478bd9Sstevel@tonic-gate ctf_data_free(base, size + hdrsz); 6627c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_CORRUPT)); 6637c478bd9Sstevel@tonic-gate } 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate ctf_data_protect(base, size + hdrsz); 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate } else { 6687c478bd9Sstevel@tonic-gate base = (void *)ctfsect->cts_data; 6697c478bd9Sstevel@tonic-gate buf = (uchar_t *)base + hdrsz; 6707c478bd9Sstevel@tonic-gate } 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate /* 6737c478bd9Sstevel@tonic-gate * Once we have uncompressed and validated the CTF data buffer, we can 6747c478bd9Sstevel@tonic-gate * proceed with allocating a ctf_file_t and initializing it. 6757c478bd9Sstevel@tonic-gate */ 6767c478bd9Sstevel@tonic-gate if ((fp = ctf_alloc(sizeof (ctf_file_t))) == NULL) 6777c478bd9Sstevel@tonic-gate return (ctf_set_open_errno(errp, EAGAIN)); 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate bzero(fp, sizeof (ctf_file_t)); 6807c478bd9Sstevel@tonic-gate fp->ctf_version = hp.cth_version; 6817c478bd9Sstevel@tonic-gate fp->ctf_fileops = &ctf_fileops[hp.cth_version]; 6827c478bd9Sstevel@tonic-gate bcopy(ctfsect, &fp->ctf_data, sizeof (ctf_sect_t)); 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate if (symsect != NULL) { 6857c478bd9Sstevel@tonic-gate bcopy(symsect, &fp->ctf_symtab, sizeof (ctf_sect_t)); 6867c478bd9Sstevel@tonic-gate bcopy(strsect, &fp->ctf_strtab, sizeof (ctf_sect_t)); 6877c478bd9Sstevel@tonic-gate } 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate if (fp->ctf_data.cts_name != NULL) 6907c478bd9Sstevel@tonic-gate fp->ctf_data.cts_name = ctf_strdup(fp->ctf_data.cts_name); 6917c478bd9Sstevel@tonic-gate if (fp->ctf_symtab.cts_name != NULL) 6927c478bd9Sstevel@tonic-gate fp->ctf_symtab.cts_name = ctf_strdup(fp->ctf_symtab.cts_name); 6937c478bd9Sstevel@tonic-gate if (fp->ctf_strtab.cts_name != NULL) 6947c478bd9Sstevel@tonic-gate fp->ctf_strtab.cts_name = ctf_strdup(fp->ctf_strtab.cts_name); 6957c478bd9Sstevel@tonic-gate 6967c478bd9Sstevel@tonic-gate if (fp->ctf_data.cts_name == NULL) 6977c478bd9Sstevel@tonic-gate fp->ctf_data.cts_name = _CTF_NULLSTR; 6987c478bd9Sstevel@tonic-gate if (fp->ctf_symtab.cts_name == NULL) 6997c478bd9Sstevel@tonic-gate fp->ctf_symtab.cts_name = _CTF_NULLSTR; 7007c478bd9Sstevel@tonic-gate if (fp->ctf_strtab.cts_name == NULL) 7017c478bd9Sstevel@tonic-gate fp->ctf_strtab.cts_name = _CTF_NULLSTR; 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate fp->ctf_str[CTF_STRTAB_0].cts_strs = (const char *)buf + hp.cth_stroff; 7047c478bd9Sstevel@tonic-gate fp->ctf_str[CTF_STRTAB_0].cts_len = hp.cth_strlen; 7057c478bd9Sstevel@tonic-gate 7067c478bd9Sstevel@tonic-gate if (strsect != NULL) { 7077c478bd9Sstevel@tonic-gate fp->ctf_str[CTF_STRTAB_1].cts_strs = strsect->cts_data; 7087c478bd9Sstevel@tonic-gate fp->ctf_str[CTF_STRTAB_1].cts_len = strsect->cts_size; 7097c478bd9Sstevel@tonic-gate } 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate fp->ctf_base = base; 7127c478bd9Sstevel@tonic-gate fp->ctf_buf = buf; 7137c478bd9Sstevel@tonic-gate fp->ctf_size = size + hdrsz; 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate /* 7167c478bd9Sstevel@tonic-gate * If we have a parent container name and label, store the relocated 7177c478bd9Sstevel@tonic-gate * string pointers in the CTF container for easy access later. 7187c478bd9Sstevel@tonic-gate */ 7197c478bd9Sstevel@tonic-gate if (hp.cth_parlabel != 0) 7207c478bd9Sstevel@tonic-gate fp->ctf_parlabel = ctf_strptr(fp, hp.cth_parlabel); 7217c478bd9Sstevel@tonic-gate if (hp.cth_parname != 0) 7227c478bd9Sstevel@tonic-gate fp->ctf_parname = ctf_strptr(fp, hp.cth_parname); 7237c478bd9Sstevel@tonic-gate 7247c478bd9Sstevel@tonic-gate ctf_dprintf("ctf_bufopen: parent name %s (label %s)\n", 7257c478bd9Sstevel@tonic-gate fp->ctf_parname ? fp->ctf_parname : "<NULL>", 7267c478bd9Sstevel@tonic-gate fp->ctf_parlabel ? fp->ctf_parlabel : "<NULL>"); 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate /* 7297c478bd9Sstevel@tonic-gate * If we have a symbol table section, allocate and initialize 7307c478bd9Sstevel@tonic-gate * the symtab translation table, pointed to by ctf_sxlate. 7317c478bd9Sstevel@tonic-gate */ 7327c478bd9Sstevel@tonic-gate if (symsect != NULL) { 7337c478bd9Sstevel@tonic-gate fp->ctf_nsyms = symsect->cts_size / symsect->cts_entsize; 7347c478bd9Sstevel@tonic-gate fp->ctf_sxlate = ctf_alloc(fp->ctf_nsyms * sizeof (uint_t)); 7357c478bd9Sstevel@tonic-gate 7367c478bd9Sstevel@tonic-gate if (fp->ctf_sxlate == NULL) { 7377c478bd9Sstevel@tonic-gate (void) ctf_set_open_errno(errp, EAGAIN); 7387c478bd9Sstevel@tonic-gate goto bad; 7397c478bd9Sstevel@tonic-gate } 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate if ((err = init_symtab(fp, &hp, symsect, strsect)) != 0) { 7427c478bd9Sstevel@tonic-gate (void) ctf_set_open_errno(errp, err); 7437c478bd9Sstevel@tonic-gate goto bad; 7447c478bd9Sstevel@tonic-gate } 7457c478bd9Sstevel@tonic-gate } 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate if ((err = init_types(fp, &hp)) != 0) { 7487c478bd9Sstevel@tonic-gate (void) ctf_set_open_errno(errp, err); 7497c478bd9Sstevel@tonic-gate goto bad; 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate /* 7537c478bd9Sstevel@tonic-gate * Initialize the ctf_lookup_by_name top-level dictionary. We keep an 7547c478bd9Sstevel@tonic-gate * array of type name prefixes and the corresponding ctf_hash to use. 7557c478bd9Sstevel@tonic-gate * NOTE: This code must be kept in sync with the code in ctf_update(). 7567c478bd9Sstevel@tonic-gate */ 7577c478bd9Sstevel@tonic-gate fp->ctf_lookups[0].ctl_prefix = "struct"; 7587c478bd9Sstevel@tonic-gate fp->ctf_lookups[0].ctl_len = strlen(fp->ctf_lookups[0].ctl_prefix); 7597c478bd9Sstevel@tonic-gate fp->ctf_lookups[0].ctl_hash = &fp->ctf_structs; 7607c478bd9Sstevel@tonic-gate fp->ctf_lookups[1].ctl_prefix = "union"; 7617c478bd9Sstevel@tonic-gate fp->ctf_lookups[1].ctl_len = strlen(fp->ctf_lookups[1].ctl_prefix); 7627c478bd9Sstevel@tonic-gate fp->ctf_lookups[1].ctl_hash = &fp->ctf_unions; 7637c478bd9Sstevel@tonic-gate fp->ctf_lookups[2].ctl_prefix = "enum"; 7647c478bd9Sstevel@tonic-gate fp->ctf_lookups[2].ctl_len = strlen(fp->ctf_lookups[2].ctl_prefix); 7657c478bd9Sstevel@tonic-gate fp->ctf_lookups[2].ctl_hash = &fp->ctf_enums; 7667c478bd9Sstevel@tonic-gate fp->ctf_lookups[3].ctl_prefix = _CTF_NULLSTR; 7677c478bd9Sstevel@tonic-gate fp->ctf_lookups[3].ctl_len = strlen(fp->ctf_lookups[3].ctl_prefix); 7687c478bd9Sstevel@tonic-gate fp->ctf_lookups[3].ctl_hash = &fp->ctf_names; 7697c478bd9Sstevel@tonic-gate fp->ctf_lookups[4].ctl_prefix = NULL; 7707c478bd9Sstevel@tonic-gate fp->ctf_lookups[4].ctl_len = 0; 7717c478bd9Sstevel@tonic-gate fp->ctf_lookups[4].ctl_hash = NULL; 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate if (symsect != NULL) { 7747c478bd9Sstevel@tonic-gate if (symsect->cts_entsize == sizeof (Elf64_Sym)) 7757c478bd9Sstevel@tonic-gate (void) ctf_setmodel(fp, CTF_MODEL_LP64); 7767c478bd9Sstevel@tonic-gate else 7777c478bd9Sstevel@tonic-gate (void) ctf_setmodel(fp, CTF_MODEL_ILP32); 7787c478bd9Sstevel@tonic-gate } else 7797c478bd9Sstevel@tonic-gate (void) ctf_setmodel(fp, CTF_MODEL_NATIVE); 7807c478bd9Sstevel@tonic-gate 7817c478bd9Sstevel@tonic-gate fp->ctf_refcnt = 1; 7827c478bd9Sstevel@tonic-gate return (fp); 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate bad: 7857c478bd9Sstevel@tonic-gate ctf_close(fp); 7867c478bd9Sstevel@tonic-gate return (NULL); 7877c478bd9Sstevel@tonic-gate } 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate /* 7907c478bd9Sstevel@tonic-gate * Close the specified CTF container and free associated data structures. Note 7917c478bd9Sstevel@tonic-gate * that ctf_close() is a reference counted operation: if the specified file is 7927c478bd9Sstevel@tonic-gate * the parent of other active containers, its reference count will be greater 7937c478bd9Sstevel@tonic-gate * than one and it will be freed later when no active children exist. 7947c478bd9Sstevel@tonic-gate */ 7957c478bd9Sstevel@tonic-gate void 7967c478bd9Sstevel@tonic-gate ctf_close(ctf_file_t *fp) 7977c478bd9Sstevel@tonic-gate { 7987c478bd9Sstevel@tonic-gate ctf_dtdef_t *dtd, *ntd; 7997c478bd9Sstevel@tonic-gate 8007c478bd9Sstevel@tonic-gate if (fp == NULL) 8017c478bd9Sstevel@tonic-gate return; /* allow ctf_close(NULL) to simplify caller code */ 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate ctf_dprintf("ctf_close(%p) refcnt=%u\n", (void *)fp, fp->ctf_refcnt); 8047c478bd9Sstevel@tonic-gate 8057c478bd9Sstevel@tonic-gate if (fp->ctf_refcnt > 1) { 8067c478bd9Sstevel@tonic-gate fp->ctf_refcnt--; 8077c478bd9Sstevel@tonic-gate return; 8087c478bd9Sstevel@tonic-gate } 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate if (fp->ctf_parent != NULL) 8117c478bd9Sstevel@tonic-gate ctf_close(fp->ctf_parent); 8127c478bd9Sstevel@tonic-gate 813*e4586ebfSmws for (dtd = ctf_list_next(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) { 814*e4586ebfSmws ntd = ctf_list_next(dtd); 815*e4586ebfSmws ctf_dtd_delete(fp, dtd); 816*e4586ebfSmws } 817*e4586ebfSmws 818*e4586ebfSmws ctf_free(fp->ctf_dthash, fp->ctf_dthashlen * sizeof (ctf_dtdef_t *)); 819*e4586ebfSmws 8207c478bd9Sstevel@tonic-gate if (fp->ctf_flags & LCTF_MMAP) { 8217c478bd9Sstevel@tonic-gate if (fp->ctf_data.cts_data != NULL) 8227c478bd9Sstevel@tonic-gate ctf_sect_munmap(&fp->ctf_data); 8237c478bd9Sstevel@tonic-gate if (fp->ctf_symtab.cts_data != NULL) 8247c478bd9Sstevel@tonic-gate ctf_sect_munmap(&fp->ctf_symtab); 8257c478bd9Sstevel@tonic-gate if (fp->ctf_strtab.cts_data != NULL) 8267c478bd9Sstevel@tonic-gate ctf_sect_munmap(&fp->ctf_strtab); 8277c478bd9Sstevel@tonic-gate } 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate if (fp->ctf_data.cts_name != _CTF_NULLSTR && 8307c478bd9Sstevel@tonic-gate fp->ctf_data.cts_name != NULL) { 8317c478bd9Sstevel@tonic-gate ctf_free((char *)fp->ctf_data.cts_name, 8327c478bd9Sstevel@tonic-gate strlen(fp->ctf_data.cts_name) + 1); 8337c478bd9Sstevel@tonic-gate } 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate if (fp->ctf_symtab.cts_name != _CTF_NULLSTR && 8367c478bd9Sstevel@tonic-gate fp->ctf_symtab.cts_name != NULL) { 8377c478bd9Sstevel@tonic-gate ctf_free((char *)fp->ctf_symtab.cts_name, 8387c478bd9Sstevel@tonic-gate strlen(fp->ctf_symtab.cts_name) + 1); 8397c478bd9Sstevel@tonic-gate } 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate if (fp->ctf_strtab.cts_name != _CTF_NULLSTR && 8427c478bd9Sstevel@tonic-gate fp->ctf_strtab.cts_name != NULL) { 8437c478bd9Sstevel@tonic-gate ctf_free((char *)fp->ctf_strtab.cts_name, 8447c478bd9Sstevel@tonic-gate strlen(fp->ctf_strtab.cts_name) + 1); 8457c478bd9Sstevel@tonic-gate } 8467c478bd9Sstevel@tonic-gate 8477c478bd9Sstevel@tonic-gate if (fp->ctf_base != fp->ctf_data.cts_data && fp->ctf_base != NULL) 8487c478bd9Sstevel@tonic-gate ctf_data_free((void *)fp->ctf_base, fp->ctf_size); 8497c478bd9Sstevel@tonic-gate 8507c478bd9Sstevel@tonic-gate if (fp->ctf_sxlate != NULL) 8517c478bd9Sstevel@tonic-gate ctf_free(fp->ctf_sxlate, sizeof (uint_t) * fp->ctf_nsyms); 8527c478bd9Sstevel@tonic-gate 8537c478bd9Sstevel@tonic-gate if (fp->ctf_txlate != NULL) { 8547c478bd9Sstevel@tonic-gate ctf_free(fp->ctf_txlate, 8557c478bd9Sstevel@tonic-gate sizeof (uint_t) * (fp->ctf_typemax + 1)); 8567c478bd9Sstevel@tonic-gate } 8577c478bd9Sstevel@tonic-gate 8587c478bd9Sstevel@tonic-gate if (fp->ctf_ptrtab != NULL) { 8597c478bd9Sstevel@tonic-gate ctf_free(fp->ctf_ptrtab, 8607c478bd9Sstevel@tonic-gate sizeof (ushort_t) * (fp->ctf_typemax + 1)); 8617c478bd9Sstevel@tonic-gate } 8627c478bd9Sstevel@tonic-gate 8637c478bd9Sstevel@tonic-gate ctf_hash_destroy(&fp->ctf_structs); 8647c478bd9Sstevel@tonic-gate ctf_hash_destroy(&fp->ctf_unions); 8657c478bd9Sstevel@tonic-gate ctf_hash_destroy(&fp->ctf_enums); 8667c478bd9Sstevel@tonic-gate ctf_hash_destroy(&fp->ctf_names); 8677c478bd9Sstevel@tonic-gate 8687c478bd9Sstevel@tonic-gate ctf_free(fp, sizeof (ctf_file_t)); 8697c478bd9Sstevel@tonic-gate } 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate /* 8727c478bd9Sstevel@tonic-gate * Return the CTF handle for the parent CTF container, if one exists. 8737c478bd9Sstevel@tonic-gate * Otherwise return NULL to indicate this container has no imported parent. 8747c478bd9Sstevel@tonic-gate */ 8757c478bd9Sstevel@tonic-gate ctf_file_t * 8767c478bd9Sstevel@tonic-gate ctf_parent_file(ctf_file_t *fp) 8777c478bd9Sstevel@tonic-gate { 8787c478bd9Sstevel@tonic-gate return (fp->ctf_parent); 8797c478bd9Sstevel@tonic-gate } 8807c478bd9Sstevel@tonic-gate 8817c478bd9Sstevel@tonic-gate /* 8827c478bd9Sstevel@tonic-gate * Return the name of the parent CTF container, if one exists. Otherwise 8837c478bd9Sstevel@tonic-gate * return NULL to indicate this container is a root container. 8847c478bd9Sstevel@tonic-gate */ 8857c478bd9Sstevel@tonic-gate const char * 8867c478bd9Sstevel@tonic-gate ctf_parent_name(ctf_file_t *fp) 8877c478bd9Sstevel@tonic-gate { 8887c478bd9Sstevel@tonic-gate return (fp->ctf_parname); 8897c478bd9Sstevel@tonic-gate } 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate /* 8927c478bd9Sstevel@tonic-gate * Import the types from the specified parent container by storing a pointer 8937c478bd9Sstevel@tonic-gate * to it in ctf_parent and incrementing its reference count. Only one parent 8947c478bd9Sstevel@tonic-gate * is allowed: if a parent already exists, it is replaced by the new parent. 8957c478bd9Sstevel@tonic-gate */ 8967c478bd9Sstevel@tonic-gate int 8977c478bd9Sstevel@tonic-gate ctf_import(ctf_file_t *fp, ctf_file_t *pfp) 8987c478bd9Sstevel@tonic-gate { 8997c478bd9Sstevel@tonic-gate if (fp == NULL || fp == pfp || (pfp != NULL && pfp->ctf_refcnt == 0)) 9007c478bd9Sstevel@tonic-gate return (ctf_set_errno(fp, EINVAL)); 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate if (pfp != NULL && pfp->ctf_dmodel != fp->ctf_dmodel) 9037c478bd9Sstevel@tonic-gate return (ctf_set_errno(fp, ECTF_DMODEL)); 9047c478bd9Sstevel@tonic-gate 9057c478bd9Sstevel@tonic-gate if (fp->ctf_parent != NULL) 9067c478bd9Sstevel@tonic-gate ctf_close(fp->ctf_parent); 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate if (pfp != NULL) { 9097c478bd9Sstevel@tonic-gate fp->ctf_flags |= LCTF_CHILD; 9107c478bd9Sstevel@tonic-gate pfp->ctf_refcnt++; 9117c478bd9Sstevel@tonic-gate } 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate fp->ctf_parent = pfp; 9147c478bd9Sstevel@tonic-gate return (0); 9157c478bd9Sstevel@tonic-gate } 9167c478bd9Sstevel@tonic-gate 9177c478bd9Sstevel@tonic-gate /* 9187c478bd9Sstevel@tonic-gate * Set the data model constant for the CTF container. 9197c478bd9Sstevel@tonic-gate */ 9207c478bd9Sstevel@tonic-gate int 9217c478bd9Sstevel@tonic-gate ctf_setmodel(ctf_file_t *fp, int model) 9227c478bd9Sstevel@tonic-gate { 9237c478bd9Sstevel@tonic-gate const ctf_dmodel_t *dp; 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate for (dp = _libctf_models; dp->ctd_name != NULL; dp++) { 9267c478bd9Sstevel@tonic-gate if (dp->ctd_code == model) { 9277c478bd9Sstevel@tonic-gate fp->ctf_dmodel = dp; 9287c478bd9Sstevel@tonic-gate return (0); 9297c478bd9Sstevel@tonic-gate } 9307c478bd9Sstevel@tonic-gate } 9317c478bd9Sstevel@tonic-gate 9327c478bd9Sstevel@tonic-gate return (ctf_set_errno(fp, EINVAL)); 9337c478bd9Sstevel@tonic-gate } 9347c478bd9Sstevel@tonic-gate 9357c478bd9Sstevel@tonic-gate /* 9367c478bd9Sstevel@tonic-gate * Return the data model constant for the CTF container. 9377c478bd9Sstevel@tonic-gate */ 9387c478bd9Sstevel@tonic-gate int 9397c478bd9Sstevel@tonic-gate ctf_getmodel(ctf_file_t *fp) 9407c478bd9Sstevel@tonic-gate { 9417c478bd9Sstevel@tonic-gate return (fp->ctf_dmodel->ctd_code); 9427c478bd9Sstevel@tonic-gate } 9437c478bd9Sstevel@tonic-gate 9447c478bd9Sstevel@tonic-gate void 9457c478bd9Sstevel@tonic-gate ctf_setspecific(ctf_file_t *fp, void *data) 9467c478bd9Sstevel@tonic-gate { 9477c478bd9Sstevel@tonic-gate fp->ctf_specific = data; 9487c478bd9Sstevel@tonic-gate } 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate void * 9517c478bd9Sstevel@tonic-gate ctf_getspecific(ctf_file_t *fp) 9527c478bd9Sstevel@tonic-gate { 9537c478bd9Sstevel@tonic-gate return (fp->ctf_specific); 9547c478bd9Sstevel@tonic-gate } 955