1*d876124dSJohn Birrell /* 2*d876124dSJohn Birrell * CDDL HEADER START 3*d876124dSJohn Birrell * 4*d876124dSJohn Birrell * The contents of this file are subject to the terms of the 5*d876124dSJohn Birrell * Common Development and Distribution License, Version 1.0 only 6*d876124dSJohn Birrell * (the "License"). You may not use this file except in compliance 7*d876124dSJohn Birrell * with the License. 8*d876124dSJohn Birrell * 9*d876124dSJohn Birrell * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*d876124dSJohn Birrell * or http://www.opensolaris.org/os/licensing. 11*d876124dSJohn Birrell * See the License for the specific language governing permissions 12*d876124dSJohn Birrell * and limitations under the License. 13*d876124dSJohn Birrell * 14*d876124dSJohn Birrell * When distributing Covered Code, include this CDDL HEADER in each 15*d876124dSJohn Birrell * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*d876124dSJohn Birrell * If applicable, add the following below this CDDL HEADER, with the 17*d876124dSJohn Birrell * fields enclosed by brackets "[]" replaced with your own identifying 18*d876124dSJohn Birrell * information: Portions Copyright [yyyy] [name of copyright owner] 19*d876124dSJohn Birrell * 20*d876124dSJohn Birrell * CDDL HEADER END 21*d876124dSJohn Birrell */ 22*d876124dSJohn Birrell 23*d876124dSJohn Birrell /* 24*d876124dSJohn Birrell * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 25*d876124dSJohn Birrell * Use is subject to license terms. 26*d876124dSJohn Birrell */ 27*d876124dSJohn Birrell 28*d876124dSJohn Birrell #pragma ident "%Z%%M% %I% %E% SMI" 29*d876124dSJohn Birrell 30*d876124dSJohn Birrell #include <ctf_impl.h> 31*d876124dSJohn Birrell #include <sys/mman.h> 32*d876124dSJohn Birrell #include <sys/zmod.h> 33*d876124dSJohn Birrell 34*d876124dSJohn Birrell static const ctf_dmodel_t _libctf_models[] = { 35*d876124dSJohn Birrell { "ILP32", CTF_MODEL_ILP32, 4, 1, 2, 4, 4 }, 36*d876124dSJohn Birrell { "LP64", CTF_MODEL_LP64, 8, 1, 2, 4, 8 }, 37*d876124dSJohn Birrell { NULL, 0, 0, 0, 0, 0, 0 } 38*d876124dSJohn Birrell }; 39*d876124dSJohn Birrell 40*d876124dSJohn Birrell const char _CTF_SECTION[] = ".SUNW_ctf"; 41*d876124dSJohn Birrell const char _CTF_NULLSTR[] = ""; 42*d876124dSJohn Birrell 43*d876124dSJohn Birrell int _libctf_version = CTF_VERSION; /* library client version */ 44*d876124dSJohn Birrell int _libctf_debug = 0; /* debugging messages enabled */ 45*d876124dSJohn Birrell 46*d876124dSJohn Birrell static ushort_t 47*d876124dSJohn Birrell get_kind_v1(ushort_t info) 48*d876124dSJohn Birrell { 49*d876124dSJohn Birrell return (CTF_INFO_KIND_V1(info)); 50*d876124dSJohn Birrell } 51*d876124dSJohn Birrell 52*d876124dSJohn Birrell static ushort_t 53*d876124dSJohn Birrell get_kind_v2(ushort_t info) 54*d876124dSJohn Birrell { 55*d876124dSJohn Birrell return (CTF_INFO_KIND(info)); 56*d876124dSJohn Birrell } 57*d876124dSJohn Birrell 58*d876124dSJohn Birrell static ushort_t 59*d876124dSJohn Birrell get_root_v1(ushort_t info) 60*d876124dSJohn Birrell { 61*d876124dSJohn Birrell return (CTF_INFO_ISROOT_V1(info)); 62*d876124dSJohn Birrell } 63*d876124dSJohn Birrell 64*d876124dSJohn Birrell static ushort_t 65*d876124dSJohn Birrell get_root_v2(ushort_t info) 66*d876124dSJohn Birrell { 67*d876124dSJohn Birrell return (CTF_INFO_ISROOT(info)); 68*d876124dSJohn Birrell } 69*d876124dSJohn Birrell 70*d876124dSJohn Birrell static ushort_t 71*d876124dSJohn Birrell get_vlen_v1(ushort_t info) 72*d876124dSJohn Birrell { 73*d876124dSJohn Birrell return (CTF_INFO_VLEN_V1(info)); 74*d876124dSJohn Birrell } 75*d876124dSJohn Birrell 76*d876124dSJohn Birrell static ushort_t 77*d876124dSJohn Birrell get_vlen_v2(ushort_t info) 78*d876124dSJohn Birrell { 79*d876124dSJohn Birrell return (CTF_INFO_VLEN(info)); 80*d876124dSJohn Birrell } 81*d876124dSJohn Birrell 82*d876124dSJohn Birrell static const ctf_fileops_t ctf_fileops[] = { 83*d876124dSJohn Birrell { NULL, NULL }, 84*d876124dSJohn Birrell { get_kind_v1, get_root_v1, get_vlen_v1 }, 85*d876124dSJohn Birrell { get_kind_v2, get_root_v2, get_vlen_v2 }, 86*d876124dSJohn Birrell }; 87*d876124dSJohn Birrell 88*d876124dSJohn Birrell /* 89*d876124dSJohn Birrell * Convert a 32-bit ELF symbol into GElf (Elf64) and return a pointer to it. 90*d876124dSJohn Birrell */ 91*d876124dSJohn Birrell static Elf64_Sym * 92*d876124dSJohn Birrell sym_to_gelf(const Elf32_Sym *src, Elf64_Sym *dst) 93*d876124dSJohn Birrell { 94*d876124dSJohn Birrell dst->st_name = src->st_name; 95*d876124dSJohn Birrell dst->st_value = src->st_value; 96*d876124dSJohn Birrell dst->st_size = src->st_size; 97*d876124dSJohn Birrell dst->st_info = src->st_info; 98*d876124dSJohn Birrell dst->st_other = src->st_other; 99*d876124dSJohn Birrell dst->st_shndx = src->st_shndx; 100*d876124dSJohn Birrell 101*d876124dSJohn Birrell return (dst); 102*d876124dSJohn Birrell } 103*d876124dSJohn Birrell 104*d876124dSJohn Birrell /* 105*d876124dSJohn Birrell * Initialize the symtab translation table by filling each entry with the 106*d876124dSJohn Birrell * offset of the CTF type or function data corresponding to each STT_FUNC or 107*d876124dSJohn Birrell * STT_OBJECT entry in the symbol table. 108*d876124dSJohn Birrell */ 109*d876124dSJohn Birrell static int 110*d876124dSJohn Birrell init_symtab(ctf_file_t *fp, const ctf_header_t *hp, 111*d876124dSJohn Birrell const ctf_sect_t *sp, const ctf_sect_t *strp) 112*d876124dSJohn Birrell { 113*d876124dSJohn Birrell const uchar_t *symp = sp->cts_data; 114*d876124dSJohn Birrell uint_t *xp = fp->ctf_sxlate; 115*d876124dSJohn Birrell uint_t *xend = xp + fp->ctf_nsyms; 116*d876124dSJohn Birrell 117*d876124dSJohn Birrell uint_t objtoff = hp->cth_objtoff; 118*d876124dSJohn Birrell uint_t funcoff = hp->cth_funcoff; 119*d876124dSJohn Birrell 120*d876124dSJohn Birrell ushort_t info, vlen; 121*d876124dSJohn Birrell Elf64_Sym sym, *gsp; 122*d876124dSJohn Birrell const char *name; 123*d876124dSJohn Birrell 124*d876124dSJohn Birrell /* 125*d876124dSJohn Birrell * The CTF data object and function type sections are ordered to match 126*d876124dSJohn Birrell * the relative order of the respective symbol types in the symtab. 127*d876124dSJohn Birrell * If no type information is available for a symbol table entry, a 128*d876124dSJohn Birrell * pad is inserted in the CTF section. As a further optimization, 129*d876124dSJohn Birrell * anonymous or undefined symbols are omitted from the CTF data. 130*d876124dSJohn Birrell */ 131*d876124dSJohn Birrell for (; xp < xend; xp++, symp += sp->cts_entsize) { 132*d876124dSJohn Birrell if (sp->cts_entsize == sizeof (Elf32_Sym)) 133*d876124dSJohn Birrell gsp = sym_to_gelf((Elf32_Sym *)(uintptr_t)symp, &sym); 134*d876124dSJohn Birrell else 135*d876124dSJohn Birrell gsp = (Elf64_Sym *)(uintptr_t)symp; 136*d876124dSJohn Birrell 137*d876124dSJohn Birrell if (gsp->st_name < strp->cts_size) 138*d876124dSJohn Birrell name = (const char *)strp->cts_data + gsp->st_name; 139*d876124dSJohn Birrell else 140*d876124dSJohn Birrell name = _CTF_NULLSTR; 141*d876124dSJohn Birrell 142*d876124dSJohn Birrell if (gsp->st_name == 0 || gsp->st_shndx == SHN_UNDEF || 143*d876124dSJohn Birrell strcmp(name, "_START_") == 0 || 144*d876124dSJohn Birrell strcmp(name, "_END_") == 0) { 145*d876124dSJohn Birrell *xp = -1u; 146*d876124dSJohn Birrell continue; 147*d876124dSJohn Birrell } 148*d876124dSJohn Birrell 149*d876124dSJohn Birrell switch (ELF64_ST_TYPE(gsp->st_info)) { 150*d876124dSJohn Birrell case STT_OBJECT: 151*d876124dSJohn Birrell if (objtoff >= hp->cth_funcoff || 152*d876124dSJohn Birrell (gsp->st_shndx == SHN_ABS && gsp->st_value == 0)) { 153*d876124dSJohn Birrell *xp = -1u; 154*d876124dSJohn Birrell break; 155*d876124dSJohn Birrell } 156*d876124dSJohn Birrell 157*d876124dSJohn Birrell *xp = objtoff; 158*d876124dSJohn Birrell objtoff += sizeof (ushort_t); 159*d876124dSJohn Birrell break; 160*d876124dSJohn Birrell 161*d876124dSJohn Birrell case STT_FUNC: 162*d876124dSJohn Birrell if (funcoff >= hp->cth_typeoff) { 163*d876124dSJohn Birrell *xp = -1u; 164*d876124dSJohn Birrell break; 165*d876124dSJohn Birrell } 166*d876124dSJohn Birrell 167*d876124dSJohn Birrell *xp = funcoff; 168*d876124dSJohn Birrell 169*d876124dSJohn Birrell info = *(ushort_t *)((uintptr_t)fp->ctf_buf + funcoff); 170*d876124dSJohn Birrell vlen = LCTF_INFO_VLEN(fp, info); 171*d876124dSJohn Birrell 172*d876124dSJohn Birrell /* 173*d876124dSJohn Birrell * If we encounter a zero pad at the end, just skip it. 174*d876124dSJohn Birrell * Otherwise skip over the function and its return type 175*d876124dSJohn Birrell * (+2) and the argument list (vlen). 176*d876124dSJohn Birrell */ 177*d876124dSJohn Birrell if (LCTF_INFO_KIND(fp, info) == CTF_K_UNKNOWN && 178*d876124dSJohn Birrell vlen == 0) 179*d876124dSJohn Birrell funcoff += sizeof (ushort_t); /* skip pad */ 180*d876124dSJohn Birrell else 181*d876124dSJohn Birrell funcoff += sizeof (ushort_t) * (vlen + 2); 182*d876124dSJohn Birrell break; 183*d876124dSJohn Birrell 184*d876124dSJohn Birrell default: 185*d876124dSJohn Birrell *xp = -1u; 186*d876124dSJohn Birrell break; 187*d876124dSJohn Birrell } 188*d876124dSJohn Birrell } 189*d876124dSJohn Birrell 190*d876124dSJohn Birrell ctf_dprintf("loaded %lu symtab entries\n", fp->ctf_nsyms); 191*d876124dSJohn Birrell return (0); 192*d876124dSJohn Birrell } 193*d876124dSJohn Birrell 194*d876124dSJohn Birrell /* 195*d876124dSJohn Birrell * Initialize the type ID translation table with the byte offset of each type, 196*d876124dSJohn Birrell * and initialize the hash tables of each named type. 197*d876124dSJohn Birrell */ 198*d876124dSJohn Birrell static int 199*d876124dSJohn Birrell init_types(ctf_file_t *fp, const ctf_header_t *cth) 200*d876124dSJohn Birrell { 201*d876124dSJohn Birrell /* LINTED - pointer alignment */ 202*d876124dSJohn Birrell const ctf_type_t *tbuf = (ctf_type_t *)(fp->ctf_buf + cth->cth_typeoff); 203*d876124dSJohn Birrell /* LINTED - pointer alignment */ 204*d876124dSJohn Birrell const ctf_type_t *tend = (ctf_type_t *)(fp->ctf_buf + cth->cth_stroff); 205*d876124dSJohn Birrell 206*d876124dSJohn Birrell ulong_t pop[CTF_K_MAX + 1] = { 0 }; 207*d876124dSJohn Birrell const ctf_type_t *tp; 208*d876124dSJohn Birrell ctf_hash_t *hp; 209*d876124dSJohn Birrell ushort_t id, dst; 210*d876124dSJohn Birrell uint_t *xp; 211*d876124dSJohn Birrell 212*d876124dSJohn Birrell /* 213*d876124dSJohn Birrell * We initially determine whether the container is a child or a parent 214*d876124dSJohn Birrell * based on the value of cth_parname. To support containers that pre- 215*d876124dSJohn Birrell * date cth_parname, we also scan the types themselves for references 216*d876124dSJohn Birrell * to values in the range reserved for child types in our first pass. 217*d876124dSJohn Birrell */ 218*d876124dSJohn Birrell int child = cth->cth_parname != 0; 219*d876124dSJohn Birrell int nlstructs = 0, nlunions = 0; 220*d876124dSJohn Birrell int err; 221*d876124dSJohn Birrell 222*d876124dSJohn Birrell /* 223*d876124dSJohn Birrell * We make two passes through the entire type section. In this first 224*d876124dSJohn Birrell * pass, we count the number of each type and the total number of types. 225*d876124dSJohn Birrell */ 226*d876124dSJohn Birrell for (tp = tbuf; tp < tend; fp->ctf_typemax++) { 227*d876124dSJohn Birrell ushort_t kind = LCTF_INFO_KIND(fp, tp->ctt_info); 228*d876124dSJohn Birrell ulong_t vlen = LCTF_INFO_VLEN(fp, tp->ctt_info); 229*d876124dSJohn Birrell ssize_t size, increment; 230*d876124dSJohn Birrell 231*d876124dSJohn Birrell size_t vbytes; 232*d876124dSJohn Birrell uint_t n; 233*d876124dSJohn Birrell 234*d876124dSJohn Birrell (void) ctf_get_ctt_size(fp, tp, &size, &increment); 235*d876124dSJohn Birrell 236*d876124dSJohn Birrell switch (kind) { 237*d876124dSJohn Birrell case CTF_K_INTEGER: 238*d876124dSJohn Birrell case CTF_K_FLOAT: 239*d876124dSJohn Birrell vbytes = sizeof (uint_t); 240*d876124dSJohn Birrell break; 241*d876124dSJohn Birrell case CTF_K_ARRAY: 242*d876124dSJohn Birrell vbytes = sizeof (ctf_array_t); 243*d876124dSJohn Birrell break; 244*d876124dSJohn Birrell case CTF_K_FUNCTION: 245*d876124dSJohn Birrell vbytes = sizeof (ushort_t) * (vlen + (vlen & 1)); 246*d876124dSJohn Birrell break; 247*d876124dSJohn Birrell case CTF_K_STRUCT: 248*d876124dSJohn Birrell case CTF_K_UNION: 249*d876124dSJohn Birrell if (fp->ctf_version == CTF_VERSION_1 || 250*d876124dSJohn Birrell size < CTF_LSTRUCT_THRESH) { 251*d876124dSJohn Birrell ctf_member_t *mp = (ctf_member_t *) 252*d876124dSJohn Birrell ((uintptr_t)tp + increment); 253*d876124dSJohn Birrell 254*d876124dSJohn Birrell vbytes = sizeof (ctf_member_t) * vlen; 255*d876124dSJohn Birrell for (n = vlen; n != 0; n--, mp++) 256*d876124dSJohn Birrell child |= CTF_TYPE_ISCHILD(mp->ctm_type); 257*d876124dSJohn Birrell } else { 258*d876124dSJohn Birrell ctf_lmember_t *lmp = (ctf_lmember_t *) 259*d876124dSJohn Birrell ((uintptr_t)tp + increment); 260*d876124dSJohn Birrell 261*d876124dSJohn Birrell vbytes = sizeof (ctf_lmember_t) * vlen; 262*d876124dSJohn Birrell for (n = vlen; n != 0; n--, lmp++) 263*d876124dSJohn Birrell child |= 264*d876124dSJohn Birrell CTF_TYPE_ISCHILD(lmp->ctlm_type); 265*d876124dSJohn Birrell } 266*d876124dSJohn Birrell break; 267*d876124dSJohn Birrell case CTF_K_ENUM: 268*d876124dSJohn Birrell vbytes = sizeof (ctf_enum_t) * vlen; 269*d876124dSJohn Birrell break; 270*d876124dSJohn Birrell case CTF_K_FORWARD: 271*d876124dSJohn Birrell /* 272*d876124dSJohn Birrell * For forward declarations, ctt_type is the CTF_K_* 273*d876124dSJohn Birrell * kind for the tag, so bump that population count too. 274*d876124dSJohn Birrell * If ctt_type is unknown, treat the tag as a struct. 275*d876124dSJohn Birrell */ 276*d876124dSJohn Birrell if (tp->ctt_type == CTF_K_UNKNOWN || 277*d876124dSJohn Birrell tp->ctt_type >= CTF_K_MAX) 278*d876124dSJohn Birrell pop[CTF_K_STRUCT]++; 279*d876124dSJohn Birrell else 280*d876124dSJohn Birrell pop[tp->ctt_type]++; 281*d876124dSJohn Birrell /*FALLTHRU*/ 282*d876124dSJohn Birrell case CTF_K_UNKNOWN: 283*d876124dSJohn Birrell vbytes = 0; 284*d876124dSJohn Birrell break; 285*d876124dSJohn Birrell case CTF_K_POINTER: 286*d876124dSJohn Birrell case CTF_K_TYPEDEF: 287*d876124dSJohn Birrell case CTF_K_VOLATILE: 288*d876124dSJohn Birrell case CTF_K_CONST: 289*d876124dSJohn Birrell case CTF_K_RESTRICT: 290*d876124dSJohn Birrell child |= CTF_TYPE_ISCHILD(tp->ctt_type); 291*d876124dSJohn Birrell vbytes = 0; 292*d876124dSJohn Birrell break; 293*d876124dSJohn Birrell default: 294*d876124dSJohn Birrell ctf_dprintf("detected invalid CTF kind -- %u\n", kind); 295*d876124dSJohn Birrell return (ECTF_CORRUPT); 296*d876124dSJohn Birrell } 297*d876124dSJohn Birrell tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes); 298*d876124dSJohn Birrell pop[kind]++; 299*d876124dSJohn Birrell } 300*d876124dSJohn Birrell 301*d876124dSJohn Birrell /* 302*d876124dSJohn Birrell * If we detected a reference to a child type ID, then we know this 303*d876124dSJohn Birrell * container is a child and may have a parent's types imported later. 304*d876124dSJohn Birrell */ 305*d876124dSJohn Birrell if (child) { 306*d876124dSJohn Birrell ctf_dprintf("CTF container %p is a child\n", (void *)fp); 307*d876124dSJohn Birrell fp->ctf_flags |= LCTF_CHILD; 308*d876124dSJohn Birrell } else 309*d876124dSJohn Birrell ctf_dprintf("CTF container %p is a parent\n", (void *)fp); 310*d876124dSJohn Birrell 311*d876124dSJohn Birrell /* 312*d876124dSJohn Birrell * Now that we've counted up the number of each type, we can allocate 313*d876124dSJohn Birrell * the hash tables, type translation table, and pointer table. 314*d876124dSJohn Birrell */ 315*d876124dSJohn Birrell if ((err = ctf_hash_create(&fp->ctf_structs, pop[CTF_K_STRUCT])) != 0) 316*d876124dSJohn Birrell return (err); 317*d876124dSJohn Birrell 318*d876124dSJohn Birrell if ((err = ctf_hash_create(&fp->ctf_unions, pop[CTF_K_UNION])) != 0) 319*d876124dSJohn Birrell return (err); 320*d876124dSJohn Birrell 321*d876124dSJohn Birrell if ((err = ctf_hash_create(&fp->ctf_enums, pop[CTF_K_ENUM])) != 0) 322*d876124dSJohn Birrell return (err); 323*d876124dSJohn Birrell 324*d876124dSJohn Birrell if ((err = ctf_hash_create(&fp->ctf_names, 325*d876124dSJohn Birrell pop[CTF_K_INTEGER] + pop[CTF_K_FLOAT] + pop[CTF_K_FUNCTION] + 326*d876124dSJohn Birrell pop[CTF_K_TYPEDEF] + pop[CTF_K_POINTER] + pop[CTF_K_VOLATILE] + 327*d876124dSJohn Birrell pop[CTF_K_CONST] + pop[CTF_K_RESTRICT])) != 0) 328*d876124dSJohn Birrell return (err); 329*d876124dSJohn Birrell 330*d876124dSJohn Birrell fp->ctf_txlate = ctf_alloc(sizeof (uint_t) * (fp->ctf_typemax + 1)); 331*d876124dSJohn Birrell fp->ctf_ptrtab = ctf_alloc(sizeof (ushort_t) * (fp->ctf_typemax + 1)); 332*d876124dSJohn Birrell 333*d876124dSJohn Birrell if (fp->ctf_txlate == NULL || fp->ctf_ptrtab == NULL) 334*d876124dSJohn Birrell return (EAGAIN); /* memory allocation failed */ 335*d876124dSJohn Birrell 336*d876124dSJohn Birrell xp = fp->ctf_txlate; 337*d876124dSJohn Birrell *xp++ = 0; /* type id 0 is used as a sentinel value */ 338*d876124dSJohn Birrell 339*d876124dSJohn Birrell bzero(fp->ctf_txlate, sizeof (uint_t) * (fp->ctf_typemax + 1)); 340*d876124dSJohn Birrell bzero(fp->ctf_ptrtab, sizeof (ushort_t) * (fp->ctf_typemax + 1)); 341*d876124dSJohn Birrell 342*d876124dSJohn Birrell /* 343*d876124dSJohn Birrell * In the second pass through the types, we fill in each entry of the 344*d876124dSJohn Birrell * type and pointer tables and add names to the appropriate hashes. 345*d876124dSJohn Birrell */ 346*d876124dSJohn Birrell for (id = 1, tp = tbuf; tp < tend; xp++, id++) { 347*d876124dSJohn Birrell ushort_t kind = LCTF_INFO_KIND(fp, tp->ctt_info); 348*d876124dSJohn Birrell ulong_t vlen = LCTF_INFO_VLEN(fp, tp->ctt_info); 349*d876124dSJohn Birrell ssize_t size, increment; 350*d876124dSJohn Birrell 351*d876124dSJohn Birrell const char *name; 352*d876124dSJohn Birrell size_t vbytes; 353*d876124dSJohn Birrell ctf_helem_t *hep; 354*d876124dSJohn Birrell ctf_encoding_t cte; 355*d876124dSJohn Birrell 356*d876124dSJohn Birrell (void) ctf_get_ctt_size(fp, tp, &size, &increment); 357*d876124dSJohn Birrell name = ctf_strptr(fp, tp->ctt_name); 358*d876124dSJohn Birrell 359*d876124dSJohn Birrell switch (kind) { 360*d876124dSJohn Birrell case CTF_K_INTEGER: 361*d876124dSJohn Birrell case CTF_K_FLOAT: 362*d876124dSJohn Birrell /* 363*d876124dSJohn Birrell * Only insert a new integer base type definition if 364*d876124dSJohn Birrell * this type name has not been defined yet. We re-use 365*d876124dSJohn Birrell * the names with different encodings for bit-fields. 366*d876124dSJohn Birrell */ 367*d876124dSJohn Birrell if ((hep = ctf_hash_lookup(&fp->ctf_names, fp, 368*d876124dSJohn Birrell name, strlen(name))) == NULL) { 369*d876124dSJohn Birrell err = ctf_hash_insert(&fp->ctf_names, fp, 370*d876124dSJohn Birrell CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 371*d876124dSJohn Birrell if (err != 0 && err != ECTF_STRTAB) 372*d876124dSJohn Birrell return (err); 373*d876124dSJohn Birrell } else if (ctf_type_encoding(fp, hep->h_type, 374*d876124dSJohn Birrell &cte) == 0 && cte.cte_bits == 0) { 375*d876124dSJohn Birrell /* 376*d876124dSJohn Birrell * Work-around SOS8 stabs bug: replace existing 377*d876124dSJohn Birrell * intrinsic w/ same name if it was zero bits. 378*d876124dSJohn Birrell */ 379*d876124dSJohn Birrell hep->h_type = CTF_INDEX_TO_TYPE(id, child); 380*d876124dSJohn Birrell } 381*d876124dSJohn Birrell vbytes = sizeof (uint_t); 382*d876124dSJohn Birrell break; 383*d876124dSJohn Birrell 384*d876124dSJohn Birrell case CTF_K_ARRAY: 385*d876124dSJohn Birrell vbytes = sizeof (ctf_array_t); 386*d876124dSJohn Birrell break; 387*d876124dSJohn Birrell 388*d876124dSJohn Birrell case CTF_K_FUNCTION: 389*d876124dSJohn Birrell err = ctf_hash_insert(&fp->ctf_names, fp, 390*d876124dSJohn Birrell CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 391*d876124dSJohn Birrell if (err != 0 && err != ECTF_STRTAB) 392*d876124dSJohn Birrell return (err); 393*d876124dSJohn Birrell vbytes = sizeof (ushort_t) * (vlen + (vlen & 1)); 394*d876124dSJohn Birrell break; 395*d876124dSJohn Birrell 396*d876124dSJohn Birrell case CTF_K_STRUCT: 397*d876124dSJohn Birrell err = ctf_hash_define(&fp->ctf_structs, fp, 398*d876124dSJohn Birrell CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 399*d876124dSJohn Birrell 400*d876124dSJohn Birrell if (err != 0 && err != ECTF_STRTAB) 401*d876124dSJohn Birrell return (err); 402*d876124dSJohn Birrell 403*d876124dSJohn Birrell if (fp->ctf_version == CTF_VERSION_1 || 404*d876124dSJohn Birrell size < CTF_LSTRUCT_THRESH) 405*d876124dSJohn Birrell vbytes = sizeof (ctf_member_t) * vlen; 406*d876124dSJohn Birrell else { 407*d876124dSJohn Birrell vbytes = sizeof (ctf_lmember_t) * vlen; 408*d876124dSJohn Birrell nlstructs++; 409*d876124dSJohn Birrell } 410*d876124dSJohn Birrell break; 411*d876124dSJohn Birrell 412*d876124dSJohn Birrell case CTF_K_UNION: 413*d876124dSJohn Birrell err = ctf_hash_define(&fp->ctf_unions, fp, 414*d876124dSJohn Birrell CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 415*d876124dSJohn Birrell 416*d876124dSJohn Birrell if (err != 0 && err != ECTF_STRTAB) 417*d876124dSJohn Birrell return (err); 418*d876124dSJohn Birrell 419*d876124dSJohn Birrell if (fp->ctf_version == CTF_VERSION_1 || 420*d876124dSJohn Birrell size < CTF_LSTRUCT_THRESH) 421*d876124dSJohn Birrell vbytes = sizeof (ctf_member_t) * vlen; 422*d876124dSJohn Birrell else { 423*d876124dSJohn Birrell vbytes = sizeof (ctf_lmember_t) * vlen; 424*d876124dSJohn Birrell nlunions++; 425*d876124dSJohn Birrell } 426*d876124dSJohn Birrell break; 427*d876124dSJohn Birrell 428*d876124dSJohn Birrell case CTF_K_ENUM: 429*d876124dSJohn Birrell err = ctf_hash_define(&fp->ctf_enums, fp, 430*d876124dSJohn Birrell CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 431*d876124dSJohn Birrell 432*d876124dSJohn Birrell if (err != 0 && err != ECTF_STRTAB) 433*d876124dSJohn Birrell return (err); 434*d876124dSJohn Birrell 435*d876124dSJohn Birrell vbytes = sizeof (ctf_enum_t) * vlen; 436*d876124dSJohn Birrell break; 437*d876124dSJohn Birrell 438*d876124dSJohn Birrell case CTF_K_TYPEDEF: 439*d876124dSJohn Birrell err = ctf_hash_insert(&fp->ctf_names, fp, 440*d876124dSJohn Birrell CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 441*d876124dSJohn Birrell if (err != 0 && err != ECTF_STRTAB) 442*d876124dSJohn Birrell return (err); 443*d876124dSJohn Birrell vbytes = 0; 444*d876124dSJohn Birrell break; 445*d876124dSJohn Birrell 446*d876124dSJohn Birrell case CTF_K_FORWARD: 447*d876124dSJohn Birrell /* 448*d876124dSJohn Birrell * Only insert forward tags into the given hash if the 449*d876124dSJohn Birrell * type or tag name is not already present. 450*d876124dSJohn Birrell */ 451*d876124dSJohn Birrell switch (tp->ctt_type) { 452*d876124dSJohn Birrell case CTF_K_STRUCT: 453*d876124dSJohn Birrell hp = &fp->ctf_structs; 454*d876124dSJohn Birrell break; 455*d876124dSJohn Birrell case CTF_K_UNION: 456*d876124dSJohn Birrell hp = &fp->ctf_unions; 457*d876124dSJohn Birrell break; 458*d876124dSJohn Birrell case CTF_K_ENUM: 459*d876124dSJohn Birrell hp = &fp->ctf_enums; 460*d876124dSJohn Birrell break; 461*d876124dSJohn Birrell default: 462*d876124dSJohn Birrell hp = &fp->ctf_structs; 463*d876124dSJohn Birrell } 464*d876124dSJohn Birrell 465*d876124dSJohn Birrell if (ctf_hash_lookup(hp, fp, 466*d876124dSJohn Birrell name, strlen(name)) == NULL) { 467*d876124dSJohn Birrell err = ctf_hash_insert(hp, fp, 468*d876124dSJohn Birrell CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 469*d876124dSJohn Birrell if (err != 0 && err != ECTF_STRTAB) 470*d876124dSJohn Birrell return (err); 471*d876124dSJohn Birrell } 472*d876124dSJohn Birrell vbytes = 0; 473*d876124dSJohn Birrell break; 474*d876124dSJohn Birrell 475*d876124dSJohn Birrell case CTF_K_POINTER: 476*d876124dSJohn Birrell /* 477*d876124dSJohn Birrell * If the type referenced by the pointer is in this CTF 478*d876124dSJohn Birrell * container, then store the index of the pointer type 479*d876124dSJohn Birrell * in fp->ctf_ptrtab[ index of referenced type ]. 480*d876124dSJohn Birrell */ 481*d876124dSJohn Birrell if (CTF_TYPE_ISCHILD(tp->ctt_type) == child && 482*d876124dSJohn Birrell CTF_TYPE_TO_INDEX(tp->ctt_type) <= fp->ctf_typemax) 483*d876124dSJohn Birrell fp->ctf_ptrtab[ 484*d876124dSJohn Birrell CTF_TYPE_TO_INDEX(tp->ctt_type)] = id; 485*d876124dSJohn Birrell /*FALLTHRU*/ 486*d876124dSJohn Birrell 487*d876124dSJohn Birrell case CTF_K_VOLATILE: 488*d876124dSJohn Birrell case CTF_K_CONST: 489*d876124dSJohn Birrell case CTF_K_RESTRICT: 490*d876124dSJohn Birrell err = ctf_hash_insert(&fp->ctf_names, fp, 491*d876124dSJohn Birrell CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); 492*d876124dSJohn Birrell if (err != 0 && err != ECTF_STRTAB) 493*d876124dSJohn Birrell return (err); 494*d876124dSJohn Birrell /*FALLTHRU*/ 495*d876124dSJohn Birrell 496*d876124dSJohn Birrell default: 497*d876124dSJohn Birrell vbytes = 0; 498*d876124dSJohn Birrell break; 499*d876124dSJohn Birrell } 500*d876124dSJohn Birrell 501*d876124dSJohn Birrell *xp = (uint_t)((uintptr_t)tp - (uintptr_t)fp->ctf_buf); 502*d876124dSJohn Birrell tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes); 503*d876124dSJohn Birrell } 504*d876124dSJohn Birrell 505*d876124dSJohn Birrell ctf_dprintf("%lu total types processed\n", fp->ctf_typemax); 506*d876124dSJohn Birrell ctf_dprintf("%u enum names hashed\n", ctf_hash_size(&fp->ctf_enums)); 507*d876124dSJohn Birrell ctf_dprintf("%u struct names hashed (%d long)\n", 508*d876124dSJohn Birrell ctf_hash_size(&fp->ctf_structs), nlstructs); 509*d876124dSJohn Birrell ctf_dprintf("%u union names hashed (%d long)\n", 510*d876124dSJohn Birrell ctf_hash_size(&fp->ctf_unions), nlunions); 511*d876124dSJohn Birrell ctf_dprintf("%u base type names hashed\n", 512*d876124dSJohn Birrell ctf_hash_size(&fp->ctf_names)); 513*d876124dSJohn Birrell 514*d876124dSJohn Birrell /* 515*d876124dSJohn Birrell * Make an additional pass through the pointer table to find pointers 516*d876124dSJohn Birrell * that point to anonymous typedef nodes. If we find one, modify the 517*d876124dSJohn Birrell * pointer table so that the pointer is also known to point to the 518*d876124dSJohn Birrell * node that is referenced by the anonymous typedef node. 519*d876124dSJohn Birrell */ 520*d876124dSJohn Birrell for (id = 1; id <= fp->ctf_typemax; id++) { 521*d876124dSJohn Birrell if ((dst = fp->ctf_ptrtab[id]) != 0) { 522*d876124dSJohn Birrell tp = LCTF_INDEX_TO_TYPEPTR(fp, id); 523*d876124dSJohn Birrell 524*d876124dSJohn Birrell if (LCTF_INFO_KIND(fp, tp->ctt_info) == CTF_K_TYPEDEF && 525*d876124dSJohn Birrell strcmp(ctf_strptr(fp, tp->ctt_name), "") == 0 && 526*d876124dSJohn Birrell CTF_TYPE_ISCHILD(tp->ctt_type) == child && 527*d876124dSJohn Birrell CTF_TYPE_TO_INDEX(tp->ctt_type) <= fp->ctf_typemax) 528*d876124dSJohn Birrell fp->ctf_ptrtab[ 529*d876124dSJohn Birrell CTF_TYPE_TO_INDEX(tp->ctt_type)] = dst; 530*d876124dSJohn Birrell } 531*d876124dSJohn Birrell } 532*d876124dSJohn Birrell 533*d876124dSJohn Birrell return (0); 534*d876124dSJohn Birrell } 535*d876124dSJohn Birrell 536*d876124dSJohn Birrell /* 537*d876124dSJohn Birrell * Decode the specified CTF buffer and optional symbol table and create a new 538*d876124dSJohn Birrell * CTF container representing the symbolic debugging information. This code 539*d876124dSJohn Birrell * can be used directly by the debugger, or it can be used as the engine for 540*d876124dSJohn Birrell * ctf_fdopen() or ctf_open(), below. 541*d876124dSJohn Birrell */ 542*d876124dSJohn Birrell ctf_file_t * 543*d876124dSJohn Birrell ctf_bufopen(const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, 544*d876124dSJohn Birrell const ctf_sect_t *strsect, int *errp) 545*d876124dSJohn Birrell { 546*d876124dSJohn Birrell const ctf_preamble_t *pp; 547*d876124dSJohn Birrell ctf_header_t hp; 548*d876124dSJohn Birrell ctf_file_t *fp; 549*d876124dSJohn Birrell void *buf, *base; 550*d876124dSJohn Birrell size_t size, hdrsz; 551*d876124dSJohn Birrell int err; 552*d876124dSJohn Birrell 553*d876124dSJohn Birrell if (ctfsect == NULL || ((symsect == NULL) != (strsect == NULL))) 554*d876124dSJohn Birrell return (ctf_set_open_errno(errp, EINVAL)); 555*d876124dSJohn Birrell 556*d876124dSJohn Birrell if (symsect != NULL && symsect->cts_entsize != sizeof (Elf32_Sym) && 557*d876124dSJohn Birrell symsect->cts_entsize != sizeof (Elf64_Sym)) 558*d876124dSJohn Birrell return (ctf_set_open_errno(errp, ECTF_SYMTAB)); 559*d876124dSJohn Birrell 560*d876124dSJohn Birrell if (symsect != NULL && symsect->cts_data == NULL) 561*d876124dSJohn Birrell return (ctf_set_open_errno(errp, ECTF_SYMBAD)); 562*d876124dSJohn Birrell 563*d876124dSJohn Birrell if (strsect != NULL && strsect->cts_data == NULL) 564*d876124dSJohn Birrell return (ctf_set_open_errno(errp, ECTF_STRBAD)); 565*d876124dSJohn Birrell 566*d876124dSJohn Birrell if (ctfsect->cts_size < sizeof (ctf_preamble_t)) 567*d876124dSJohn Birrell return (ctf_set_open_errno(errp, ECTF_NOCTFBUF)); 568*d876124dSJohn Birrell 569*d876124dSJohn Birrell pp = (const ctf_preamble_t *)ctfsect->cts_data; 570*d876124dSJohn Birrell 571*d876124dSJohn Birrell ctf_dprintf("ctf_bufopen: magic=0x%x version=%u\n", 572*d876124dSJohn Birrell pp->ctp_magic, pp->ctp_version); 573*d876124dSJohn Birrell 574*d876124dSJohn Birrell /* 575*d876124dSJohn Birrell * Validate each part of the CTF header (either V1 or V2). 576*d876124dSJohn Birrell * First, we validate the preamble (common to all versions). At that 577*d876124dSJohn Birrell * point, we know specific header version, and can validate the 578*d876124dSJohn Birrell * version-specific parts including section offsets and alignments. 579*d876124dSJohn Birrell */ 580*d876124dSJohn Birrell if (pp->ctp_magic != CTF_MAGIC) 581*d876124dSJohn Birrell return (ctf_set_open_errno(errp, ECTF_NOCTFBUF)); 582*d876124dSJohn Birrell 583*d876124dSJohn Birrell if (pp->ctp_version == CTF_VERSION_2) { 584*d876124dSJohn Birrell if (ctfsect->cts_size < sizeof (ctf_header_t)) 585*d876124dSJohn Birrell return (ctf_set_open_errno(errp, ECTF_NOCTFBUF)); 586*d876124dSJohn Birrell 587*d876124dSJohn Birrell bcopy(ctfsect->cts_data, &hp, sizeof (hp)); 588*d876124dSJohn Birrell hdrsz = sizeof (ctf_header_t); 589*d876124dSJohn Birrell 590*d876124dSJohn Birrell } else if (pp->ctp_version == CTF_VERSION_1) { 591*d876124dSJohn Birrell const ctf_header_v1_t *h1p = 592*d876124dSJohn Birrell (const ctf_header_v1_t *)ctfsect->cts_data; 593*d876124dSJohn Birrell 594*d876124dSJohn Birrell if (ctfsect->cts_size < sizeof (ctf_header_v1_t)) 595*d876124dSJohn Birrell return (ctf_set_open_errno(errp, ECTF_NOCTFBUF)); 596*d876124dSJohn Birrell 597*d876124dSJohn Birrell bzero(&hp, sizeof (hp)); 598*d876124dSJohn Birrell hp.cth_preamble = h1p->cth_preamble; 599*d876124dSJohn Birrell hp.cth_objtoff = h1p->cth_objtoff; 600*d876124dSJohn Birrell hp.cth_funcoff = h1p->cth_funcoff; 601*d876124dSJohn Birrell hp.cth_typeoff = h1p->cth_typeoff; 602*d876124dSJohn Birrell hp.cth_stroff = h1p->cth_stroff; 603*d876124dSJohn Birrell hp.cth_strlen = h1p->cth_strlen; 604*d876124dSJohn Birrell 605*d876124dSJohn Birrell hdrsz = sizeof (ctf_header_v1_t); 606*d876124dSJohn Birrell } else 607*d876124dSJohn Birrell return (ctf_set_open_errno(errp, ECTF_CTFVERS)); 608*d876124dSJohn Birrell 609*d876124dSJohn Birrell size = hp.cth_stroff + hp.cth_strlen; 610*d876124dSJohn Birrell 611*d876124dSJohn Birrell ctf_dprintf("ctf_bufopen: uncompressed size=%lu\n", (ulong_t)size); 612*d876124dSJohn Birrell 613*d876124dSJohn Birrell if (hp.cth_lbloff > size || hp.cth_objtoff > size || 614*d876124dSJohn Birrell hp.cth_funcoff > size || hp.cth_typeoff > size || 615*d876124dSJohn Birrell hp.cth_stroff > size) 616*d876124dSJohn Birrell return (ctf_set_open_errno(errp, ECTF_CORRUPT)); 617*d876124dSJohn Birrell 618*d876124dSJohn Birrell if (hp.cth_lbloff > hp.cth_objtoff || 619*d876124dSJohn Birrell hp.cth_objtoff > hp.cth_funcoff || 620*d876124dSJohn Birrell hp.cth_funcoff > hp.cth_typeoff || 621*d876124dSJohn Birrell hp.cth_typeoff > hp.cth_stroff) 622*d876124dSJohn Birrell return (ctf_set_open_errno(errp, ECTF_CORRUPT)); 623*d876124dSJohn Birrell 624*d876124dSJohn Birrell if ((hp.cth_lbloff & 3) || (hp.cth_objtoff & 1) || 625*d876124dSJohn Birrell (hp.cth_funcoff & 1) || (hp.cth_typeoff & 3)) 626*d876124dSJohn Birrell return (ctf_set_open_errno(errp, ECTF_CORRUPT)); 627*d876124dSJohn Birrell 628*d876124dSJohn Birrell /* 629*d876124dSJohn Birrell * Once everything is determined to be valid, attempt to decompress 630*d876124dSJohn Birrell * the CTF data buffer if it is compressed. Otherwise we just put 631*d876124dSJohn Birrell * the data section's buffer pointer into ctf_buf, below. 632*d876124dSJohn Birrell */ 633*d876124dSJohn Birrell if (hp.cth_flags & CTF_F_COMPRESS) { 634*d876124dSJohn Birrell size_t srclen, dstlen; 635*d876124dSJohn Birrell const void *src; 636*d876124dSJohn Birrell int rc = Z_OK; 637*d876124dSJohn Birrell 638*d876124dSJohn Birrell if (ctf_zopen(errp) == NULL) 639*d876124dSJohn Birrell return (NULL); /* errp is set for us */ 640*d876124dSJohn Birrell 641*d876124dSJohn Birrell if ((base = ctf_data_alloc(size + hdrsz)) == MAP_FAILED) 642*d876124dSJohn Birrell return (ctf_set_open_errno(errp, ECTF_ZALLOC)); 643*d876124dSJohn Birrell 644*d876124dSJohn Birrell bcopy(ctfsect->cts_data, base, hdrsz); 645*d876124dSJohn Birrell ((ctf_preamble_t *)base)->ctp_flags &= ~CTF_F_COMPRESS; 646*d876124dSJohn Birrell buf = (uchar_t *)base + hdrsz; 647*d876124dSJohn Birrell 648*d876124dSJohn Birrell src = (uchar_t *)ctfsect->cts_data + hdrsz; 649*d876124dSJohn Birrell srclen = ctfsect->cts_size - hdrsz; 650*d876124dSJohn Birrell dstlen = size; 651*d876124dSJohn Birrell 652*d876124dSJohn Birrell if ((rc = z_uncompress(buf, &dstlen, src, srclen)) != Z_OK) { 653*d876124dSJohn Birrell ctf_dprintf("zlib inflate err: %s\n", z_strerror(rc)); 654*d876124dSJohn Birrell ctf_data_free(base, size + hdrsz); 655*d876124dSJohn Birrell return (ctf_set_open_errno(errp, ECTF_DECOMPRESS)); 656*d876124dSJohn Birrell } 657*d876124dSJohn Birrell 658*d876124dSJohn Birrell if (dstlen != size) { 659*d876124dSJohn Birrell ctf_dprintf("zlib inflate short -- got %lu of %lu " 660*d876124dSJohn Birrell "bytes\n", (ulong_t)dstlen, (ulong_t)size); 661*d876124dSJohn Birrell ctf_data_free(base, size + hdrsz); 662*d876124dSJohn Birrell return (ctf_set_open_errno(errp, ECTF_CORRUPT)); 663*d876124dSJohn Birrell } 664*d876124dSJohn Birrell 665*d876124dSJohn Birrell ctf_data_protect(base, size + hdrsz); 666*d876124dSJohn Birrell 667*d876124dSJohn Birrell } else { 668*d876124dSJohn Birrell base = (void *)ctfsect->cts_data; 669*d876124dSJohn Birrell buf = (uchar_t *)base + hdrsz; 670*d876124dSJohn Birrell } 671*d876124dSJohn Birrell 672*d876124dSJohn Birrell /* 673*d876124dSJohn Birrell * Once we have uncompressed and validated the CTF data buffer, we can 674*d876124dSJohn Birrell * proceed with allocating a ctf_file_t and initializing it. 675*d876124dSJohn Birrell */ 676*d876124dSJohn Birrell if ((fp = ctf_alloc(sizeof (ctf_file_t))) == NULL) 677*d876124dSJohn Birrell return (ctf_set_open_errno(errp, EAGAIN)); 678*d876124dSJohn Birrell 679*d876124dSJohn Birrell bzero(fp, sizeof (ctf_file_t)); 680*d876124dSJohn Birrell fp->ctf_version = hp.cth_version; 681*d876124dSJohn Birrell fp->ctf_fileops = &ctf_fileops[hp.cth_version]; 682*d876124dSJohn Birrell bcopy(ctfsect, &fp->ctf_data, sizeof (ctf_sect_t)); 683*d876124dSJohn Birrell 684*d876124dSJohn Birrell if (symsect != NULL) { 685*d876124dSJohn Birrell bcopy(symsect, &fp->ctf_symtab, sizeof (ctf_sect_t)); 686*d876124dSJohn Birrell bcopy(strsect, &fp->ctf_strtab, sizeof (ctf_sect_t)); 687*d876124dSJohn Birrell } 688*d876124dSJohn Birrell 689*d876124dSJohn Birrell if (fp->ctf_data.cts_name != NULL) 690*d876124dSJohn Birrell fp->ctf_data.cts_name = ctf_strdup(fp->ctf_data.cts_name); 691*d876124dSJohn Birrell if (fp->ctf_symtab.cts_name != NULL) 692*d876124dSJohn Birrell fp->ctf_symtab.cts_name = ctf_strdup(fp->ctf_symtab.cts_name); 693*d876124dSJohn Birrell if (fp->ctf_strtab.cts_name != NULL) 694*d876124dSJohn Birrell fp->ctf_strtab.cts_name = ctf_strdup(fp->ctf_strtab.cts_name); 695*d876124dSJohn Birrell 696*d876124dSJohn Birrell if (fp->ctf_data.cts_name == NULL) 697*d876124dSJohn Birrell fp->ctf_data.cts_name = _CTF_NULLSTR; 698*d876124dSJohn Birrell if (fp->ctf_symtab.cts_name == NULL) 699*d876124dSJohn Birrell fp->ctf_symtab.cts_name = _CTF_NULLSTR; 700*d876124dSJohn Birrell if (fp->ctf_strtab.cts_name == NULL) 701*d876124dSJohn Birrell fp->ctf_strtab.cts_name = _CTF_NULLSTR; 702*d876124dSJohn Birrell 703*d876124dSJohn Birrell fp->ctf_str[CTF_STRTAB_0].cts_strs = (const char *)buf + hp.cth_stroff; 704*d876124dSJohn Birrell fp->ctf_str[CTF_STRTAB_0].cts_len = hp.cth_strlen; 705*d876124dSJohn Birrell 706*d876124dSJohn Birrell if (strsect != NULL) { 707*d876124dSJohn Birrell fp->ctf_str[CTF_STRTAB_1].cts_strs = strsect->cts_data; 708*d876124dSJohn Birrell fp->ctf_str[CTF_STRTAB_1].cts_len = strsect->cts_size; 709*d876124dSJohn Birrell } 710*d876124dSJohn Birrell 711*d876124dSJohn Birrell fp->ctf_base = base; 712*d876124dSJohn Birrell fp->ctf_buf = buf; 713*d876124dSJohn Birrell fp->ctf_size = size + hdrsz; 714*d876124dSJohn Birrell 715*d876124dSJohn Birrell /* 716*d876124dSJohn Birrell * If we have a parent container name and label, store the relocated 717*d876124dSJohn Birrell * string pointers in the CTF container for easy access later. 718*d876124dSJohn Birrell */ 719*d876124dSJohn Birrell if (hp.cth_parlabel != 0) 720*d876124dSJohn Birrell fp->ctf_parlabel = ctf_strptr(fp, hp.cth_parlabel); 721*d876124dSJohn Birrell if (hp.cth_parname != 0) 722*d876124dSJohn Birrell fp->ctf_parname = ctf_strptr(fp, hp.cth_parname); 723*d876124dSJohn Birrell 724*d876124dSJohn Birrell ctf_dprintf("ctf_bufopen: parent name %s (label %s)\n", 725*d876124dSJohn Birrell fp->ctf_parname ? fp->ctf_parname : "<NULL>", 726*d876124dSJohn Birrell fp->ctf_parlabel ? fp->ctf_parlabel : "<NULL>"); 727*d876124dSJohn Birrell 728*d876124dSJohn Birrell /* 729*d876124dSJohn Birrell * If we have a symbol table section, allocate and initialize 730*d876124dSJohn Birrell * the symtab translation table, pointed to by ctf_sxlate. 731*d876124dSJohn Birrell */ 732*d876124dSJohn Birrell if (symsect != NULL) { 733*d876124dSJohn Birrell fp->ctf_nsyms = symsect->cts_size / symsect->cts_entsize; 734*d876124dSJohn Birrell fp->ctf_sxlate = ctf_alloc(fp->ctf_nsyms * sizeof (uint_t)); 735*d876124dSJohn Birrell 736*d876124dSJohn Birrell if (fp->ctf_sxlate == NULL) { 737*d876124dSJohn Birrell (void) ctf_set_open_errno(errp, EAGAIN); 738*d876124dSJohn Birrell goto bad; 739*d876124dSJohn Birrell } 740*d876124dSJohn Birrell 741*d876124dSJohn Birrell if ((err = init_symtab(fp, &hp, symsect, strsect)) != 0) { 742*d876124dSJohn Birrell (void) ctf_set_open_errno(errp, err); 743*d876124dSJohn Birrell goto bad; 744*d876124dSJohn Birrell } 745*d876124dSJohn Birrell } 746*d876124dSJohn Birrell 747*d876124dSJohn Birrell if ((err = init_types(fp, &hp)) != 0) { 748*d876124dSJohn Birrell (void) ctf_set_open_errno(errp, err); 749*d876124dSJohn Birrell goto bad; 750*d876124dSJohn Birrell } 751*d876124dSJohn Birrell 752*d876124dSJohn Birrell /* 753*d876124dSJohn Birrell * Initialize the ctf_lookup_by_name top-level dictionary. We keep an 754*d876124dSJohn Birrell * array of type name prefixes and the corresponding ctf_hash to use. 755*d876124dSJohn Birrell * NOTE: This code must be kept in sync with the code in ctf_update(). 756*d876124dSJohn Birrell */ 757*d876124dSJohn Birrell fp->ctf_lookups[0].ctl_prefix = "struct"; 758*d876124dSJohn Birrell fp->ctf_lookups[0].ctl_len = strlen(fp->ctf_lookups[0].ctl_prefix); 759*d876124dSJohn Birrell fp->ctf_lookups[0].ctl_hash = &fp->ctf_structs; 760*d876124dSJohn Birrell fp->ctf_lookups[1].ctl_prefix = "union"; 761*d876124dSJohn Birrell fp->ctf_lookups[1].ctl_len = strlen(fp->ctf_lookups[1].ctl_prefix); 762*d876124dSJohn Birrell fp->ctf_lookups[1].ctl_hash = &fp->ctf_unions; 763*d876124dSJohn Birrell fp->ctf_lookups[2].ctl_prefix = "enum"; 764*d876124dSJohn Birrell fp->ctf_lookups[2].ctl_len = strlen(fp->ctf_lookups[2].ctl_prefix); 765*d876124dSJohn Birrell fp->ctf_lookups[2].ctl_hash = &fp->ctf_enums; 766*d876124dSJohn Birrell fp->ctf_lookups[3].ctl_prefix = _CTF_NULLSTR; 767*d876124dSJohn Birrell fp->ctf_lookups[3].ctl_len = strlen(fp->ctf_lookups[3].ctl_prefix); 768*d876124dSJohn Birrell fp->ctf_lookups[3].ctl_hash = &fp->ctf_names; 769*d876124dSJohn Birrell fp->ctf_lookups[4].ctl_prefix = NULL; 770*d876124dSJohn Birrell fp->ctf_lookups[4].ctl_len = 0; 771*d876124dSJohn Birrell fp->ctf_lookups[4].ctl_hash = NULL; 772*d876124dSJohn Birrell 773*d876124dSJohn Birrell if (symsect != NULL) { 774*d876124dSJohn Birrell if (symsect->cts_entsize == sizeof (Elf64_Sym)) 775*d876124dSJohn Birrell (void) ctf_setmodel(fp, CTF_MODEL_LP64); 776*d876124dSJohn Birrell else 777*d876124dSJohn Birrell (void) ctf_setmodel(fp, CTF_MODEL_ILP32); 778*d876124dSJohn Birrell } else 779*d876124dSJohn Birrell (void) ctf_setmodel(fp, CTF_MODEL_NATIVE); 780*d876124dSJohn Birrell 781*d876124dSJohn Birrell fp->ctf_refcnt = 1; 782*d876124dSJohn Birrell return (fp); 783*d876124dSJohn Birrell 784*d876124dSJohn Birrell bad: 785*d876124dSJohn Birrell ctf_close(fp); 786*d876124dSJohn Birrell return (NULL); 787*d876124dSJohn Birrell } 788*d876124dSJohn Birrell 789*d876124dSJohn Birrell /* 790*d876124dSJohn Birrell * Close the specified CTF container and free associated data structures. Note 791*d876124dSJohn Birrell * that ctf_close() is a reference counted operation: if the specified file is 792*d876124dSJohn Birrell * the parent of other active containers, its reference count will be greater 793*d876124dSJohn Birrell * than one and it will be freed later when no active children exist. 794*d876124dSJohn Birrell */ 795*d876124dSJohn Birrell void 796*d876124dSJohn Birrell ctf_close(ctf_file_t *fp) 797*d876124dSJohn Birrell { 798*d876124dSJohn Birrell ctf_dtdef_t *dtd, *ntd; 799*d876124dSJohn Birrell 800*d876124dSJohn Birrell if (fp == NULL) 801*d876124dSJohn Birrell return; /* allow ctf_close(NULL) to simplify caller code */ 802*d876124dSJohn Birrell 803*d876124dSJohn Birrell ctf_dprintf("ctf_close(%p) refcnt=%u\n", (void *)fp, fp->ctf_refcnt); 804*d876124dSJohn Birrell 805*d876124dSJohn Birrell if (fp->ctf_refcnt > 1) { 806*d876124dSJohn Birrell fp->ctf_refcnt--; 807*d876124dSJohn Birrell return; 808*d876124dSJohn Birrell } 809*d876124dSJohn Birrell 810*d876124dSJohn Birrell if (fp->ctf_parent != NULL) 811*d876124dSJohn Birrell ctf_close(fp->ctf_parent); 812*d876124dSJohn Birrell 813*d876124dSJohn Birrell for (dtd = ctf_list_next(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) { 814*d876124dSJohn Birrell ntd = ctf_list_next(dtd); 815*d876124dSJohn Birrell ctf_dtd_delete(fp, dtd); 816*d876124dSJohn Birrell } 817*d876124dSJohn Birrell 818*d876124dSJohn Birrell ctf_free(fp->ctf_dthash, fp->ctf_dthashlen * sizeof (ctf_dtdef_t *)); 819*d876124dSJohn Birrell 820*d876124dSJohn Birrell if (fp->ctf_flags & LCTF_MMAP) { 821*d876124dSJohn Birrell if (fp->ctf_data.cts_data != NULL) 822*d876124dSJohn Birrell ctf_sect_munmap(&fp->ctf_data); 823*d876124dSJohn Birrell if (fp->ctf_symtab.cts_data != NULL) 824*d876124dSJohn Birrell ctf_sect_munmap(&fp->ctf_symtab); 825*d876124dSJohn Birrell if (fp->ctf_strtab.cts_data != NULL) 826*d876124dSJohn Birrell ctf_sect_munmap(&fp->ctf_strtab); 827*d876124dSJohn Birrell } 828*d876124dSJohn Birrell 829*d876124dSJohn Birrell if (fp->ctf_data.cts_name != _CTF_NULLSTR && 830*d876124dSJohn Birrell fp->ctf_data.cts_name != NULL) { 831*d876124dSJohn Birrell ctf_free((char *)fp->ctf_data.cts_name, 832*d876124dSJohn Birrell strlen(fp->ctf_data.cts_name) + 1); 833*d876124dSJohn Birrell } 834*d876124dSJohn Birrell 835*d876124dSJohn Birrell if (fp->ctf_symtab.cts_name != _CTF_NULLSTR && 836*d876124dSJohn Birrell fp->ctf_symtab.cts_name != NULL) { 837*d876124dSJohn Birrell ctf_free((char *)fp->ctf_symtab.cts_name, 838*d876124dSJohn Birrell strlen(fp->ctf_symtab.cts_name) + 1); 839*d876124dSJohn Birrell } 840*d876124dSJohn Birrell 841*d876124dSJohn Birrell if (fp->ctf_strtab.cts_name != _CTF_NULLSTR && 842*d876124dSJohn Birrell fp->ctf_strtab.cts_name != NULL) { 843*d876124dSJohn Birrell ctf_free((char *)fp->ctf_strtab.cts_name, 844*d876124dSJohn Birrell strlen(fp->ctf_strtab.cts_name) + 1); 845*d876124dSJohn Birrell } 846*d876124dSJohn Birrell 847*d876124dSJohn Birrell if (fp->ctf_base != fp->ctf_data.cts_data && fp->ctf_base != NULL) 848*d876124dSJohn Birrell ctf_data_free((void *)fp->ctf_base, fp->ctf_size); 849*d876124dSJohn Birrell 850*d876124dSJohn Birrell if (fp->ctf_sxlate != NULL) 851*d876124dSJohn Birrell ctf_free(fp->ctf_sxlate, sizeof (uint_t) * fp->ctf_nsyms); 852*d876124dSJohn Birrell 853*d876124dSJohn Birrell if (fp->ctf_txlate != NULL) { 854*d876124dSJohn Birrell ctf_free(fp->ctf_txlate, 855*d876124dSJohn Birrell sizeof (uint_t) * (fp->ctf_typemax + 1)); 856*d876124dSJohn Birrell } 857*d876124dSJohn Birrell 858*d876124dSJohn Birrell if (fp->ctf_ptrtab != NULL) { 859*d876124dSJohn Birrell ctf_free(fp->ctf_ptrtab, 860*d876124dSJohn Birrell sizeof (ushort_t) * (fp->ctf_typemax + 1)); 861*d876124dSJohn Birrell } 862*d876124dSJohn Birrell 863*d876124dSJohn Birrell ctf_hash_destroy(&fp->ctf_structs); 864*d876124dSJohn Birrell ctf_hash_destroy(&fp->ctf_unions); 865*d876124dSJohn Birrell ctf_hash_destroy(&fp->ctf_enums); 866*d876124dSJohn Birrell ctf_hash_destroy(&fp->ctf_names); 867*d876124dSJohn Birrell 868*d876124dSJohn Birrell ctf_free(fp, sizeof (ctf_file_t)); 869*d876124dSJohn Birrell } 870*d876124dSJohn Birrell 871*d876124dSJohn Birrell /* 872*d876124dSJohn Birrell * Return the CTF handle for the parent CTF container, if one exists. 873*d876124dSJohn Birrell * Otherwise return NULL to indicate this container has no imported parent. 874*d876124dSJohn Birrell */ 875*d876124dSJohn Birrell ctf_file_t * 876*d876124dSJohn Birrell ctf_parent_file(ctf_file_t *fp) 877*d876124dSJohn Birrell { 878*d876124dSJohn Birrell return (fp->ctf_parent); 879*d876124dSJohn Birrell } 880*d876124dSJohn Birrell 881*d876124dSJohn Birrell /* 882*d876124dSJohn Birrell * Return the name of the parent CTF container, if one exists. Otherwise 883*d876124dSJohn Birrell * return NULL to indicate this container is a root container. 884*d876124dSJohn Birrell */ 885*d876124dSJohn Birrell const char * 886*d876124dSJohn Birrell ctf_parent_name(ctf_file_t *fp) 887*d876124dSJohn Birrell { 888*d876124dSJohn Birrell return (fp->ctf_parname); 889*d876124dSJohn Birrell } 890*d876124dSJohn Birrell 891*d876124dSJohn Birrell /* 892*d876124dSJohn Birrell * Import the types from the specified parent container by storing a pointer 893*d876124dSJohn Birrell * to it in ctf_parent and incrementing its reference count. Only one parent 894*d876124dSJohn Birrell * is allowed: if a parent already exists, it is replaced by the new parent. 895*d876124dSJohn Birrell */ 896*d876124dSJohn Birrell int 897*d876124dSJohn Birrell ctf_import(ctf_file_t *fp, ctf_file_t *pfp) 898*d876124dSJohn Birrell { 899*d876124dSJohn Birrell if (fp == NULL || fp == pfp || (pfp != NULL && pfp->ctf_refcnt == 0)) 900*d876124dSJohn Birrell return (ctf_set_errno(fp, EINVAL)); 901*d876124dSJohn Birrell 902*d876124dSJohn Birrell if (pfp != NULL && pfp->ctf_dmodel != fp->ctf_dmodel) 903*d876124dSJohn Birrell return (ctf_set_errno(fp, ECTF_DMODEL)); 904*d876124dSJohn Birrell 905*d876124dSJohn Birrell if (fp->ctf_parent != NULL) 906*d876124dSJohn Birrell ctf_close(fp->ctf_parent); 907*d876124dSJohn Birrell 908*d876124dSJohn Birrell if (pfp != NULL) { 909*d876124dSJohn Birrell fp->ctf_flags |= LCTF_CHILD; 910*d876124dSJohn Birrell pfp->ctf_refcnt++; 911*d876124dSJohn Birrell } 912*d876124dSJohn Birrell 913*d876124dSJohn Birrell fp->ctf_parent = pfp; 914*d876124dSJohn Birrell return (0); 915*d876124dSJohn Birrell } 916*d876124dSJohn Birrell 917*d876124dSJohn Birrell /* 918*d876124dSJohn Birrell * Set the data model constant for the CTF container. 919*d876124dSJohn Birrell */ 920*d876124dSJohn Birrell int 921*d876124dSJohn Birrell ctf_setmodel(ctf_file_t *fp, int model) 922*d876124dSJohn Birrell { 923*d876124dSJohn Birrell const ctf_dmodel_t *dp; 924*d876124dSJohn Birrell 925*d876124dSJohn Birrell for (dp = _libctf_models; dp->ctd_name != NULL; dp++) { 926*d876124dSJohn Birrell if (dp->ctd_code == model) { 927*d876124dSJohn Birrell fp->ctf_dmodel = dp; 928*d876124dSJohn Birrell return (0); 929*d876124dSJohn Birrell } 930*d876124dSJohn Birrell } 931*d876124dSJohn Birrell 932*d876124dSJohn Birrell return (ctf_set_errno(fp, EINVAL)); 933*d876124dSJohn Birrell } 934*d876124dSJohn Birrell 935*d876124dSJohn Birrell /* 936*d876124dSJohn Birrell * Return the data model constant for the CTF container. 937*d876124dSJohn Birrell */ 938*d876124dSJohn Birrell int 939*d876124dSJohn Birrell ctf_getmodel(ctf_file_t *fp) 940*d876124dSJohn Birrell { 941*d876124dSJohn Birrell return (fp->ctf_dmodel->ctd_code); 942*d876124dSJohn Birrell } 943*d876124dSJohn Birrell 944*d876124dSJohn Birrell void 945*d876124dSJohn Birrell ctf_setspecific(ctf_file_t *fp, void *data) 946*d876124dSJohn Birrell { 947*d876124dSJohn Birrell fp->ctf_specific = data; 948*d876124dSJohn Birrell } 949*d876124dSJohn Birrell 950*d876124dSJohn Birrell void * 951*d876124dSJohn Birrell ctf_getspecific(ctf_file_t *fp) 952*d876124dSJohn Birrell { 953*d876124dSJohn Birrell return (fp->ctf_specific); 954*d876124dSJohn Birrell } 955