1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/sysmacros.h> 30*0Sstevel@tonic-gate #include <sys/param.h> 31*0Sstevel@tonic-gate #include <sys/mman.h> 32*0Sstevel@tonic-gate #include <ctf_impl.h> 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gate /* 35*0Sstevel@tonic-gate * This static string is used as the template for initially populating a 36*0Sstevel@tonic-gate * dynamic container's string table. We always store \0 in the first byte, 37*0Sstevel@tonic-gate * and we use the generic string "PARENT" to mark this container's parent 38*0Sstevel@tonic-gate * if one is associated with the container using ctf_import(). 39*0Sstevel@tonic-gate */ 40*0Sstevel@tonic-gate static const char _CTF_STRTAB_TEMPLATE[] = "\0PARENT"; 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate /* 43*0Sstevel@tonic-gate * To create an empty CTF container, we just declare a zeroed header and call 44*0Sstevel@tonic-gate * ctf_bufopen() on it. If ctf_bufopen succeeds, we mark the new container r/w 45*0Sstevel@tonic-gate * and initialize the dynamic members. We set dtstrlen to 1 to reserve the 46*0Sstevel@tonic-gate * first byte of the string table for a \0 byte, and we start assigning type 47*0Sstevel@tonic-gate * IDs at 1 because type ID 0 is used as a sentinel. 48*0Sstevel@tonic-gate */ 49*0Sstevel@tonic-gate ctf_file_t * 50*0Sstevel@tonic-gate ctf_create(int *errp) 51*0Sstevel@tonic-gate { 52*0Sstevel@tonic-gate static const ctf_header_t hdr = { { CTF_MAGIC, CTF_VERSION, 0 } }; 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate ctf_sect_t cts; 55*0Sstevel@tonic-gate ctf_file_t *fp; 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate cts.cts_name = _CTF_SECTION; 58*0Sstevel@tonic-gate cts.cts_type = SHT_PROGBITS; 59*0Sstevel@tonic-gate cts.cts_flags = 0; 60*0Sstevel@tonic-gate cts.cts_data = &hdr; 61*0Sstevel@tonic-gate cts.cts_size = sizeof (hdr); 62*0Sstevel@tonic-gate cts.cts_entsize = 1; 63*0Sstevel@tonic-gate cts.cts_offset = 0; 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate if ((fp = ctf_bufopen(&cts, NULL, NULL, errp)) != NULL) { 66*0Sstevel@tonic-gate fp->ctf_flags |= LCTF_RDWR; 67*0Sstevel@tonic-gate fp->ctf_dtstrlen = sizeof (_CTF_STRTAB_TEMPLATE); 68*0Sstevel@tonic-gate fp->ctf_dtnextid = 1; 69*0Sstevel@tonic-gate fp->ctf_dtoldid = 0; 70*0Sstevel@tonic-gate } 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate return (fp); 73*0Sstevel@tonic-gate } 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gate static uchar_t * 76*0Sstevel@tonic-gate ctf_copy_smembers(ctf_dtdef_t *dtd, uint_t soff, uchar_t *t) 77*0Sstevel@tonic-gate { 78*0Sstevel@tonic-gate ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members); 79*0Sstevel@tonic-gate ctf_member_t ctm; 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate for (; dmd != NULL; dmd = ctf_list_next(dmd)) { 82*0Sstevel@tonic-gate if (dmd->dmd_name) { 83*0Sstevel@tonic-gate ctm.ctm_name = soff; 84*0Sstevel@tonic-gate soff += strlen(dmd->dmd_name) + 1; 85*0Sstevel@tonic-gate } else 86*0Sstevel@tonic-gate ctm.ctm_name = 0; 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate ctm.ctm_type = (ushort_t)dmd->dmd_type; 89*0Sstevel@tonic-gate ctm.ctm_offset = (ushort_t)dmd->dmd_offset; 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate bcopy(&ctm, t, sizeof (ctm)); 92*0Sstevel@tonic-gate t += sizeof (ctm); 93*0Sstevel@tonic-gate } 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate return (t); 96*0Sstevel@tonic-gate } 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate static uchar_t * 99*0Sstevel@tonic-gate ctf_copy_lmembers(ctf_dtdef_t *dtd, uint_t soff, uchar_t *t) 100*0Sstevel@tonic-gate { 101*0Sstevel@tonic-gate ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members); 102*0Sstevel@tonic-gate ctf_lmember_t ctlm; 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate for (; dmd != NULL; dmd = ctf_list_next(dmd)) { 105*0Sstevel@tonic-gate if (dmd->dmd_name) { 106*0Sstevel@tonic-gate ctlm.ctlm_name = soff; 107*0Sstevel@tonic-gate soff += strlen(dmd->dmd_name) + 1; 108*0Sstevel@tonic-gate } else 109*0Sstevel@tonic-gate ctlm.ctlm_name = 0; 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate ctlm.ctlm_type = (ushort_t)dmd->dmd_type; 112*0Sstevel@tonic-gate ctlm.ctlm_pad = 0; 113*0Sstevel@tonic-gate ctlm.ctlm_offsethi = CTF_OFFSET_TO_LMEMHI(dmd->dmd_offset); 114*0Sstevel@tonic-gate ctlm.ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO(dmd->dmd_offset); 115*0Sstevel@tonic-gate 116*0Sstevel@tonic-gate bcopy(&ctlm, t, sizeof (ctlm)); 117*0Sstevel@tonic-gate t += sizeof (ctlm); 118*0Sstevel@tonic-gate } 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate return (t); 121*0Sstevel@tonic-gate } 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate static uchar_t * 124*0Sstevel@tonic-gate ctf_copy_emembers(ctf_dtdef_t *dtd, uint_t soff, uchar_t *t) 125*0Sstevel@tonic-gate { 126*0Sstevel@tonic-gate ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members); 127*0Sstevel@tonic-gate ctf_enum_t cte; 128*0Sstevel@tonic-gate 129*0Sstevel@tonic-gate for (; dmd != NULL; dmd = ctf_list_next(dmd)) { 130*0Sstevel@tonic-gate cte.cte_name = soff; 131*0Sstevel@tonic-gate cte.cte_value = dmd->dmd_value; 132*0Sstevel@tonic-gate soff += strlen(dmd->dmd_name) + 1; 133*0Sstevel@tonic-gate bcopy(&cte, t, sizeof (cte)); 134*0Sstevel@tonic-gate t += sizeof (cte); 135*0Sstevel@tonic-gate } 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate return (t); 138*0Sstevel@tonic-gate } 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate static uchar_t * 141*0Sstevel@tonic-gate ctf_copy_membnames(ctf_dtdef_t *dtd, uchar_t *s) 142*0Sstevel@tonic-gate { 143*0Sstevel@tonic-gate ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members); 144*0Sstevel@tonic-gate size_t len; 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate for (; dmd != NULL; dmd = ctf_list_next(dmd)) { 147*0Sstevel@tonic-gate if (dmd->dmd_name == NULL) 148*0Sstevel@tonic-gate continue; /* skip anonymous members */ 149*0Sstevel@tonic-gate len = strlen(dmd->dmd_name) + 1; 150*0Sstevel@tonic-gate bcopy(dmd->dmd_name, s, len); 151*0Sstevel@tonic-gate s += len; 152*0Sstevel@tonic-gate } 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate return (s); 155*0Sstevel@tonic-gate } 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate /* 158*0Sstevel@tonic-gate * If the specified CTF container is writable and has been modified, reload 159*0Sstevel@tonic-gate * this container with the updated type definitions. In order to make this 160*0Sstevel@tonic-gate * code and the rest of libctf as simple as possible, we perform updates by 161*0Sstevel@tonic-gate * taking the dynamic type definitions and creating an in-memory CTF file 162*0Sstevel@tonic-gate * containing the definitions, and then call ctf_bufopen() on it. This not 163*0Sstevel@tonic-gate * only leverages ctf_bufopen(), but also avoids having to bifurcate the rest 164*0Sstevel@tonic-gate * of the library code with different lookup paths for static and dynamic 165*0Sstevel@tonic-gate * type definitions. We are therefore optimizing greatly for lookup over 166*0Sstevel@tonic-gate * update, which we assume will be an uncommon operation. We perform one 167*0Sstevel@tonic-gate * extra trick here for the benefit of callers and to keep our code simple: 168*0Sstevel@tonic-gate * ctf_bufopen() will return a new ctf_file_t, but we want to keep the fp 169*0Sstevel@tonic-gate * constant for the caller, so after ctf_bufopen() returns, we use bcopy to 170*0Sstevel@tonic-gate * swap the interior of the old and new ctf_file_t's, and then free the old. 171*0Sstevel@tonic-gate */ 172*0Sstevel@tonic-gate int 173*0Sstevel@tonic-gate ctf_update(ctf_file_t *fp) 174*0Sstevel@tonic-gate { 175*0Sstevel@tonic-gate ctf_file_t ofp, *nfp; 176*0Sstevel@tonic-gate ctf_header_t hdr; 177*0Sstevel@tonic-gate ctf_dtdef_t *dtd; 178*0Sstevel@tonic-gate ctf_sect_t cts; 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate uchar_t *s, *s0, *t; 181*0Sstevel@tonic-gate size_t size; 182*0Sstevel@tonic-gate void *buf; 183*0Sstevel@tonic-gate int err; 184*0Sstevel@tonic-gate 185*0Sstevel@tonic-gate if (!(fp->ctf_flags & LCTF_RDWR)) 186*0Sstevel@tonic-gate return (ctf_set_errno(fp, ECTF_RDONLY)); 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate if (!(fp->ctf_flags & LCTF_DIRTY)) 189*0Sstevel@tonic-gate return (0); /* no update required */ 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gate /* 192*0Sstevel@tonic-gate * Fill in an initial CTF header. We will leave the label, object, 193*0Sstevel@tonic-gate * and function sections empty and only output a header, type section, 194*0Sstevel@tonic-gate * and string table. The type section begins at a 4-byte aligned 195*0Sstevel@tonic-gate * boundary past the CTF header itself (at relative offset zero). 196*0Sstevel@tonic-gate */ 197*0Sstevel@tonic-gate bzero(&hdr, sizeof (hdr)); 198*0Sstevel@tonic-gate hdr.cth_magic = CTF_MAGIC; 199*0Sstevel@tonic-gate hdr.cth_version = CTF_VERSION; 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate if (fp->ctf_flags & LCTF_CHILD) 202*0Sstevel@tonic-gate hdr.cth_parname = 1; /* i.e. _CTF_STRTAB_TEMPLATE[1] */ 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate /* 205*0Sstevel@tonic-gate * Iterate through the dynamic type definition list and compute the 206*0Sstevel@tonic-gate * size of the CTF type section we will need to generate. 207*0Sstevel@tonic-gate */ 208*0Sstevel@tonic-gate for (size = 0, dtd = ctf_list_next(&fp->ctf_dtdefs); 209*0Sstevel@tonic-gate dtd != NULL; dtd = ctf_list_next(dtd)) { 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate uint_t kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info); 212*0Sstevel@tonic-gate uint_t vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info); 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT) 215*0Sstevel@tonic-gate size += sizeof (ctf_stype_t); 216*0Sstevel@tonic-gate else 217*0Sstevel@tonic-gate size += sizeof (ctf_type_t); 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate switch (kind) { 220*0Sstevel@tonic-gate case CTF_K_INTEGER: 221*0Sstevel@tonic-gate case CTF_K_FLOAT: 222*0Sstevel@tonic-gate size += sizeof (uint_t); 223*0Sstevel@tonic-gate break; 224*0Sstevel@tonic-gate case CTF_K_ARRAY: 225*0Sstevel@tonic-gate size += sizeof (ctf_array_t); 226*0Sstevel@tonic-gate break; 227*0Sstevel@tonic-gate case CTF_K_FUNCTION: 228*0Sstevel@tonic-gate size += sizeof (ushort_t) * (vlen + (vlen & 1)); 229*0Sstevel@tonic-gate break; 230*0Sstevel@tonic-gate case CTF_K_STRUCT: 231*0Sstevel@tonic-gate case CTF_K_UNION: 232*0Sstevel@tonic-gate if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH) 233*0Sstevel@tonic-gate size += sizeof (ctf_member_t) * vlen; 234*0Sstevel@tonic-gate else 235*0Sstevel@tonic-gate size += sizeof (ctf_lmember_t) * vlen; 236*0Sstevel@tonic-gate break; 237*0Sstevel@tonic-gate case CTF_K_ENUM: 238*0Sstevel@tonic-gate size += sizeof (ctf_enum_t) * vlen; 239*0Sstevel@tonic-gate break; 240*0Sstevel@tonic-gate } 241*0Sstevel@tonic-gate } 242*0Sstevel@tonic-gate 243*0Sstevel@tonic-gate /* 244*0Sstevel@tonic-gate * Fill in the string table offset and size, compute the size of the 245*0Sstevel@tonic-gate * entire CTF buffer we need, and then allocate a new buffer and 246*0Sstevel@tonic-gate * bcopy the finished header to the start of the buffer. 247*0Sstevel@tonic-gate */ 248*0Sstevel@tonic-gate hdr.cth_stroff = hdr.cth_typeoff + size; 249*0Sstevel@tonic-gate hdr.cth_strlen = fp->ctf_dtstrlen; 250*0Sstevel@tonic-gate size = sizeof (ctf_header_t) + hdr.cth_stroff + hdr.cth_strlen; 251*0Sstevel@tonic-gate 252*0Sstevel@tonic-gate if ((buf = ctf_data_alloc(size)) == MAP_FAILED) 253*0Sstevel@tonic-gate return (ctf_set_errno(fp, EAGAIN)); 254*0Sstevel@tonic-gate 255*0Sstevel@tonic-gate bcopy(&hdr, buf, sizeof (ctf_header_t)); 256*0Sstevel@tonic-gate t = (uchar_t *)buf + sizeof (ctf_header_t); 257*0Sstevel@tonic-gate s = s0 = (uchar_t *)buf + sizeof (ctf_header_t) + hdr.cth_stroff; 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate bcopy(_CTF_STRTAB_TEMPLATE, s, sizeof (_CTF_STRTAB_TEMPLATE)); 260*0Sstevel@tonic-gate s += sizeof (_CTF_STRTAB_TEMPLATE); 261*0Sstevel@tonic-gate 262*0Sstevel@tonic-gate /* 263*0Sstevel@tonic-gate * We now take a final lap through the dynamic type definition list and 264*0Sstevel@tonic-gate * copy the appropriate type records and strings to the output buffer. 265*0Sstevel@tonic-gate */ 266*0Sstevel@tonic-gate for (dtd = ctf_list_next(&fp->ctf_dtdefs); 267*0Sstevel@tonic-gate dtd != NULL; dtd = ctf_list_next(dtd)) { 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate uint_t kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info); 270*0Sstevel@tonic-gate uint_t vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info); 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate ctf_array_t cta; 273*0Sstevel@tonic-gate uint_t encoding; 274*0Sstevel@tonic-gate size_t len; 275*0Sstevel@tonic-gate 276*0Sstevel@tonic-gate if (dtd->dtd_name != NULL) { 277*0Sstevel@tonic-gate dtd->dtd_data.ctt_name = (uint_t)(s - s0); 278*0Sstevel@tonic-gate len = strlen(dtd->dtd_name) + 1; 279*0Sstevel@tonic-gate bcopy(dtd->dtd_name, s, len); 280*0Sstevel@tonic-gate s += len; 281*0Sstevel@tonic-gate } else 282*0Sstevel@tonic-gate dtd->dtd_data.ctt_name = 0; 283*0Sstevel@tonic-gate 284*0Sstevel@tonic-gate if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT) 285*0Sstevel@tonic-gate len = sizeof (ctf_stype_t); 286*0Sstevel@tonic-gate else 287*0Sstevel@tonic-gate len = sizeof (ctf_type_t); 288*0Sstevel@tonic-gate 289*0Sstevel@tonic-gate bcopy(&dtd->dtd_data, t, len); 290*0Sstevel@tonic-gate t += len; 291*0Sstevel@tonic-gate 292*0Sstevel@tonic-gate switch (kind) { 293*0Sstevel@tonic-gate case CTF_K_INTEGER: 294*0Sstevel@tonic-gate case CTF_K_FLOAT: 295*0Sstevel@tonic-gate if (kind == CTF_K_INTEGER) { 296*0Sstevel@tonic-gate encoding = CTF_INT_DATA( 297*0Sstevel@tonic-gate dtd->dtd_u.dtu_enc.cte_format, 298*0Sstevel@tonic-gate dtd->dtd_u.dtu_enc.cte_offset, 299*0Sstevel@tonic-gate dtd->dtd_u.dtu_enc.cte_bits); 300*0Sstevel@tonic-gate } else { 301*0Sstevel@tonic-gate encoding = CTF_FP_DATA( 302*0Sstevel@tonic-gate dtd->dtd_u.dtu_enc.cte_format, 303*0Sstevel@tonic-gate dtd->dtd_u.dtu_enc.cte_offset, 304*0Sstevel@tonic-gate dtd->dtd_u.dtu_enc.cte_bits); 305*0Sstevel@tonic-gate } 306*0Sstevel@tonic-gate bcopy(&encoding, t, sizeof (encoding)); 307*0Sstevel@tonic-gate t += sizeof (encoding); 308*0Sstevel@tonic-gate break; 309*0Sstevel@tonic-gate 310*0Sstevel@tonic-gate case CTF_K_ARRAY: 311*0Sstevel@tonic-gate cta.cta_contents = (ushort_t) 312*0Sstevel@tonic-gate dtd->dtd_u.dtu_arr.ctr_contents; 313*0Sstevel@tonic-gate cta.cta_index = (ushort_t) 314*0Sstevel@tonic-gate dtd->dtd_u.dtu_arr.ctr_index; 315*0Sstevel@tonic-gate cta.cta_nelems = dtd->dtd_u.dtu_arr.ctr_nelems; 316*0Sstevel@tonic-gate bcopy(&cta, t, sizeof (cta)); 317*0Sstevel@tonic-gate t += sizeof (cta); 318*0Sstevel@tonic-gate break; 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate case CTF_K_FUNCTION: { 321*0Sstevel@tonic-gate ushort_t *argv = (ushort_t *)(uintptr_t)t; 322*0Sstevel@tonic-gate uint_t argc; 323*0Sstevel@tonic-gate 324*0Sstevel@tonic-gate for (argc = 0; argc < vlen; argc++) 325*0Sstevel@tonic-gate *argv++ = (ushort_t)dtd->dtd_u.dtu_argv[argc]; 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate if (vlen & 1) 328*0Sstevel@tonic-gate *argv++ = 0; /* pad to 4-byte boundary */ 329*0Sstevel@tonic-gate 330*0Sstevel@tonic-gate t = (uchar_t *)argv; 331*0Sstevel@tonic-gate break; 332*0Sstevel@tonic-gate } 333*0Sstevel@tonic-gate 334*0Sstevel@tonic-gate case CTF_K_STRUCT: 335*0Sstevel@tonic-gate case CTF_K_UNION: 336*0Sstevel@tonic-gate if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH) 337*0Sstevel@tonic-gate t = ctf_copy_smembers(dtd, (uint_t)(s - s0), t); 338*0Sstevel@tonic-gate else 339*0Sstevel@tonic-gate t = ctf_copy_lmembers(dtd, (uint_t)(s - s0), t); 340*0Sstevel@tonic-gate s = ctf_copy_membnames(dtd, s); 341*0Sstevel@tonic-gate break; 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate case CTF_K_ENUM: 344*0Sstevel@tonic-gate t = ctf_copy_emembers(dtd, (uint_t)(s - s0), t); 345*0Sstevel@tonic-gate s = ctf_copy_membnames(dtd, s); 346*0Sstevel@tonic-gate break; 347*0Sstevel@tonic-gate } 348*0Sstevel@tonic-gate } 349*0Sstevel@tonic-gate 350*0Sstevel@tonic-gate /* 351*0Sstevel@tonic-gate * Finally, we are ready to ctf_bufopen() the new container. If this 352*0Sstevel@tonic-gate * is successful, we then switch nfp and fp and free the old container. 353*0Sstevel@tonic-gate */ 354*0Sstevel@tonic-gate ctf_data_protect(buf, size); 355*0Sstevel@tonic-gate cts.cts_name = _CTF_SECTION; 356*0Sstevel@tonic-gate cts.cts_type = SHT_PROGBITS; 357*0Sstevel@tonic-gate cts.cts_flags = 0; 358*0Sstevel@tonic-gate cts.cts_data = buf; 359*0Sstevel@tonic-gate cts.cts_size = size; 360*0Sstevel@tonic-gate cts.cts_entsize = 1; 361*0Sstevel@tonic-gate cts.cts_offset = 0; 362*0Sstevel@tonic-gate 363*0Sstevel@tonic-gate if ((nfp = ctf_bufopen(&cts, NULL, NULL, &err)) == NULL) { 364*0Sstevel@tonic-gate ctf_data_free(buf, size); 365*0Sstevel@tonic-gate return (ctf_set_errno(fp, err)); 366*0Sstevel@tonic-gate } 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate (void) ctf_setmodel(nfp, ctf_getmodel(fp)); 369*0Sstevel@tonic-gate (void) ctf_import(nfp, fp->ctf_parent); 370*0Sstevel@tonic-gate 371*0Sstevel@tonic-gate nfp->ctf_refcnt = fp->ctf_refcnt; 372*0Sstevel@tonic-gate nfp->ctf_flags |= fp->ctf_flags & ~LCTF_DIRTY; 373*0Sstevel@tonic-gate nfp->ctf_data.cts_data = NULL; /* force ctf_data_free() on close */ 374*0Sstevel@tonic-gate nfp->ctf_dtdefs = fp->ctf_dtdefs; 375*0Sstevel@tonic-gate nfp->ctf_dtstrlen = fp->ctf_dtstrlen; 376*0Sstevel@tonic-gate nfp->ctf_dtnextid = fp->ctf_dtnextid; 377*0Sstevel@tonic-gate nfp->ctf_dtoldid = fp->ctf_dtnextid - 1; 378*0Sstevel@tonic-gate nfp->ctf_specific = fp->ctf_specific; 379*0Sstevel@tonic-gate 380*0Sstevel@tonic-gate bzero(&fp->ctf_dtdefs, sizeof (ctf_list_t)); 381*0Sstevel@tonic-gate bcopy(fp, &ofp, sizeof (ctf_file_t)); 382*0Sstevel@tonic-gate bcopy(nfp, fp, sizeof (ctf_file_t)); 383*0Sstevel@tonic-gate bcopy(&ofp, nfp, sizeof (ctf_file_t)); 384*0Sstevel@tonic-gate 385*0Sstevel@tonic-gate /* 386*0Sstevel@tonic-gate * Initialize the ctf_lookup_by_name top-level dictionary. We keep an 387*0Sstevel@tonic-gate * array of type name prefixes and the corresponding ctf_hash to use. 388*0Sstevel@tonic-gate * NOTE: This code must be kept in sync with the code in ctf_bufopen(). 389*0Sstevel@tonic-gate */ 390*0Sstevel@tonic-gate fp->ctf_lookups[0].ctl_hash = &fp->ctf_structs; 391*0Sstevel@tonic-gate fp->ctf_lookups[1].ctl_hash = &fp->ctf_unions; 392*0Sstevel@tonic-gate fp->ctf_lookups[2].ctl_hash = &fp->ctf_enums; 393*0Sstevel@tonic-gate fp->ctf_lookups[3].ctl_hash = &fp->ctf_names; 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gate nfp->ctf_refcnt = 1; /* force nfp to be freed */ 396*0Sstevel@tonic-gate ctf_close(nfp); 397*0Sstevel@tonic-gate 398*0Sstevel@tonic-gate return (0); 399*0Sstevel@tonic-gate } 400*0Sstevel@tonic-gate 401*0Sstevel@tonic-gate /* 402*0Sstevel@tonic-gate * Discard all of the dynamic type definitions that have been added to the 403*0Sstevel@tonic-gate * container since the last call to ctf_update(). We locate such types by 404*0Sstevel@tonic-gate * scanning the list and deleting elements that have type IDs greater than 405*0Sstevel@tonic-gate * ctf_dtoldid, which is set by ctf_update(), above. 406*0Sstevel@tonic-gate */ 407*0Sstevel@tonic-gate int 408*0Sstevel@tonic-gate ctf_discard(ctf_file_t *fp) 409*0Sstevel@tonic-gate { 410*0Sstevel@tonic-gate ctf_dtdef_t *dtd, *ntd; 411*0Sstevel@tonic-gate ctf_dmdef_t *dmd, *nmd; 412*0Sstevel@tonic-gate size_t len; 413*0Sstevel@tonic-gate 414*0Sstevel@tonic-gate if (!(fp->ctf_flags & LCTF_RDWR)) 415*0Sstevel@tonic-gate return (ctf_set_errno(fp, ECTF_RDONLY)); 416*0Sstevel@tonic-gate 417*0Sstevel@tonic-gate if (!(fp->ctf_flags & LCTF_DIRTY)) 418*0Sstevel@tonic-gate return (0); /* no update required */ 419*0Sstevel@tonic-gate 420*0Sstevel@tonic-gate for (dtd = ctf_list_next(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) { 421*0Sstevel@tonic-gate if (dtd->dtd_type <= fp->ctf_dtoldid) 422*0Sstevel@tonic-gate continue; /* skip types that have been committed */ 423*0Sstevel@tonic-gate 424*0Sstevel@tonic-gate switch (CTF_INFO_KIND(dtd->dtd_data.ctt_info)) { 425*0Sstevel@tonic-gate case CTF_K_STRUCT: 426*0Sstevel@tonic-gate case CTF_K_UNION: 427*0Sstevel@tonic-gate case CTF_K_ENUM: 428*0Sstevel@tonic-gate for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members); 429*0Sstevel@tonic-gate dmd != NULL; dmd = nmd) { 430*0Sstevel@tonic-gate if (dmd->dmd_name != NULL) { 431*0Sstevel@tonic-gate len = strlen(dmd->dmd_name) + 1; 432*0Sstevel@tonic-gate ctf_free(dmd->dmd_name, len); 433*0Sstevel@tonic-gate fp->ctf_dtstrlen -= len; 434*0Sstevel@tonic-gate } 435*0Sstevel@tonic-gate nmd = ctf_list_next(dmd); 436*0Sstevel@tonic-gate ctf_free(dmd, sizeof (ctf_dmdef_t)); 437*0Sstevel@tonic-gate } 438*0Sstevel@tonic-gate break; 439*0Sstevel@tonic-gate case CTF_K_FUNCTION: 440*0Sstevel@tonic-gate ctf_free(dtd->dtd_u.dtu_argv, sizeof (ctf_id_t) * 441*0Sstevel@tonic-gate CTF_INFO_VLEN(dtd->dtd_data.ctt_info)); 442*0Sstevel@tonic-gate break; 443*0Sstevel@tonic-gate } 444*0Sstevel@tonic-gate 445*0Sstevel@tonic-gate if (dtd->dtd_name) { 446*0Sstevel@tonic-gate len = strlen(dtd->dtd_name) + 1; 447*0Sstevel@tonic-gate ctf_free(dtd->dtd_name, len); 448*0Sstevel@tonic-gate fp->ctf_dtstrlen -= len; 449*0Sstevel@tonic-gate } 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate ntd = ctf_list_next(dtd); 452*0Sstevel@tonic-gate ctf_list_delete(&fp->ctf_dtdefs, dtd); 453*0Sstevel@tonic-gate ctf_free(dtd, sizeof (ctf_dtdef_t)); 454*0Sstevel@tonic-gate } 455*0Sstevel@tonic-gate 456*0Sstevel@tonic-gate fp->ctf_dtnextid = fp->ctf_dtoldid + 1; 457*0Sstevel@tonic-gate fp->ctf_flags &= ~LCTF_DIRTY; 458*0Sstevel@tonic-gate 459*0Sstevel@tonic-gate return (0); 460*0Sstevel@tonic-gate } 461*0Sstevel@tonic-gate 462*0Sstevel@tonic-gate static ctf_id_t 463*0Sstevel@tonic-gate ctf_add_generic(ctf_file_t *fp, uint_t flag, const char *name, ctf_dtdef_t **rp) 464*0Sstevel@tonic-gate { 465*0Sstevel@tonic-gate ctf_dtdef_t *dtd; 466*0Sstevel@tonic-gate ctf_id_t type; 467*0Sstevel@tonic-gate char *s = NULL; 468*0Sstevel@tonic-gate 469*0Sstevel@tonic-gate if (flag != CTF_ADD_NONROOT && flag != CTF_ADD_ROOT) 470*0Sstevel@tonic-gate return (ctf_set_errno(fp, EINVAL)); 471*0Sstevel@tonic-gate 472*0Sstevel@tonic-gate if (!(fp->ctf_flags & LCTF_RDWR)) 473*0Sstevel@tonic-gate return (ctf_set_errno(fp, ECTF_RDONLY)); 474*0Sstevel@tonic-gate 475*0Sstevel@tonic-gate if (CTF_INDEX_TO_TYPE(fp->ctf_dtnextid, 1) > CTF_MAX_TYPE) 476*0Sstevel@tonic-gate return (ctf_set_errno(fp, ECTF_FULL)); 477*0Sstevel@tonic-gate 478*0Sstevel@tonic-gate if ((dtd = ctf_alloc(sizeof (ctf_dtdef_t))) == NULL) 479*0Sstevel@tonic-gate return (ctf_set_errno(fp, EAGAIN)); 480*0Sstevel@tonic-gate 481*0Sstevel@tonic-gate if (name != NULL && (s = ctf_strdup(name)) == NULL) { 482*0Sstevel@tonic-gate ctf_free(dtd, sizeof (ctf_dtdef_t)); 483*0Sstevel@tonic-gate return (ctf_set_errno(fp, EAGAIN)); 484*0Sstevel@tonic-gate } 485*0Sstevel@tonic-gate 486*0Sstevel@tonic-gate type = fp->ctf_dtnextid++; 487*0Sstevel@tonic-gate type = CTF_INDEX_TO_TYPE(type, (fp->ctf_flags & LCTF_CHILD)); 488*0Sstevel@tonic-gate 489*0Sstevel@tonic-gate bzero(dtd, sizeof (ctf_dtdef_t)); 490*0Sstevel@tonic-gate dtd->dtd_name = s; 491*0Sstevel@tonic-gate dtd->dtd_type = type; 492*0Sstevel@tonic-gate 493*0Sstevel@tonic-gate if (s != NULL) 494*0Sstevel@tonic-gate fp->ctf_dtstrlen += strlen(s) + 1; 495*0Sstevel@tonic-gate 496*0Sstevel@tonic-gate ctf_list_append(&fp->ctf_dtdefs, dtd); 497*0Sstevel@tonic-gate fp->ctf_flags |= LCTF_DIRTY; 498*0Sstevel@tonic-gate 499*0Sstevel@tonic-gate *rp = dtd; 500*0Sstevel@tonic-gate return (type); 501*0Sstevel@tonic-gate } 502*0Sstevel@tonic-gate 503*0Sstevel@tonic-gate /* 504*0Sstevel@tonic-gate * When encoding integer sizes, we want to convert a byte count in the range 505*0Sstevel@tonic-gate * 1-8 to the closest power of 2 (e.g. 3->4, 5->8, etc). The clp2() function 506*0Sstevel@tonic-gate * is a clever implementation from "Hacker's Delight" by Henry Warren, Jr. 507*0Sstevel@tonic-gate */ 508*0Sstevel@tonic-gate static size_t 509*0Sstevel@tonic-gate clp2(size_t x) 510*0Sstevel@tonic-gate { 511*0Sstevel@tonic-gate x--; 512*0Sstevel@tonic-gate 513*0Sstevel@tonic-gate x |= (x >> 1); 514*0Sstevel@tonic-gate x |= (x >> 2); 515*0Sstevel@tonic-gate x |= (x >> 4); 516*0Sstevel@tonic-gate x |= (x >> 8); 517*0Sstevel@tonic-gate x |= (x >> 16); 518*0Sstevel@tonic-gate 519*0Sstevel@tonic-gate return (x + 1); 520*0Sstevel@tonic-gate } 521*0Sstevel@tonic-gate 522*0Sstevel@tonic-gate static ctf_id_t 523*0Sstevel@tonic-gate ctf_add_encoded(ctf_file_t *fp, uint_t flag, 524*0Sstevel@tonic-gate const char *name, const ctf_encoding_t *ep, uint_t kind) 525*0Sstevel@tonic-gate { 526*0Sstevel@tonic-gate ctf_dtdef_t *dtd; 527*0Sstevel@tonic-gate ctf_id_t type; 528*0Sstevel@tonic-gate 529*0Sstevel@tonic-gate if (ep == NULL) 530*0Sstevel@tonic-gate return (ctf_set_errno(fp, EINVAL)); 531*0Sstevel@tonic-gate 532*0Sstevel@tonic-gate if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR) 533*0Sstevel@tonic-gate return (CTF_ERR); /* errno is set for us */ 534*0Sstevel@tonic-gate 535*0Sstevel@tonic-gate dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, 0); 536*0Sstevel@tonic-gate dtd->dtd_data.ctt_size = clp2(P2ROUNDUP(ep->cte_bits, NBBY) / NBBY); 537*0Sstevel@tonic-gate dtd->dtd_u.dtu_enc = *ep; 538*0Sstevel@tonic-gate 539*0Sstevel@tonic-gate return (type); 540*0Sstevel@tonic-gate } 541*0Sstevel@tonic-gate 542*0Sstevel@tonic-gate static ctf_id_t 543*0Sstevel@tonic-gate ctf_add_reftype(ctf_file_t *fp, uint_t flag, ctf_id_t ref, uint_t kind) 544*0Sstevel@tonic-gate { 545*0Sstevel@tonic-gate ctf_dtdef_t *dtd; 546*0Sstevel@tonic-gate ctf_id_t type; 547*0Sstevel@tonic-gate 548*0Sstevel@tonic-gate if (ref == CTF_ERR || ref < 0 || ref > CTF_MAX_TYPE) 549*0Sstevel@tonic-gate return (ctf_set_errno(fp, EINVAL)); 550*0Sstevel@tonic-gate 551*0Sstevel@tonic-gate if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR) 552*0Sstevel@tonic-gate return (CTF_ERR); /* errno is set for us */ 553*0Sstevel@tonic-gate 554*0Sstevel@tonic-gate dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, 0); 555*0Sstevel@tonic-gate dtd->dtd_data.ctt_type = (ushort_t)ref; 556*0Sstevel@tonic-gate 557*0Sstevel@tonic-gate return (type); 558*0Sstevel@tonic-gate } 559*0Sstevel@tonic-gate 560*0Sstevel@tonic-gate ctf_id_t 561*0Sstevel@tonic-gate ctf_add_integer(ctf_file_t *fp, uint_t flag, 562*0Sstevel@tonic-gate const char *name, const ctf_encoding_t *ep) 563*0Sstevel@tonic-gate { 564*0Sstevel@tonic-gate return (ctf_add_encoded(fp, flag, name, ep, CTF_K_INTEGER)); 565*0Sstevel@tonic-gate } 566*0Sstevel@tonic-gate 567*0Sstevel@tonic-gate ctf_id_t 568*0Sstevel@tonic-gate ctf_add_float(ctf_file_t *fp, uint_t flag, 569*0Sstevel@tonic-gate const char *name, const ctf_encoding_t *ep) 570*0Sstevel@tonic-gate { 571*0Sstevel@tonic-gate return (ctf_add_encoded(fp, flag, name, ep, CTF_K_FLOAT)); 572*0Sstevel@tonic-gate } 573*0Sstevel@tonic-gate 574*0Sstevel@tonic-gate ctf_id_t 575*0Sstevel@tonic-gate ctf_add_pointer(ctf_file_t *fp, uint_t flag, ctf_id_t ref) 576*0Sstevel@tonic-gate { 577*0Sstevel@tonic-gate return (ctf_add_reftype(fp, flag, ref, CTF_K_POINTER)); 578*0Sstevel@tonic-gate } 579*0Sstevel@tonic-gate 580*0Sstevel@tonic-gate ctf_id_t 581*0Sstevel@tonic-gate ctf_add_array(ctf_file_t *fp, uint_t flag, const ctf_arinfo_t *arp) 582*0Sstevel@tonic-gate { 583*0Sstevel@tonic-gate ctf_dtdef_t *dtd; 584*0Sstevel@tonic-gate ctf_id_t type; 585*0Sstevel@tonic-gate 586*0Sstevel@tonic-gate if (arp == NULL) 587*0Sstevel@tonic-gate return (ctf_set_errno(fp, EINVAL)); 588*0Sstevel@tonic-gate 589*0Sstevel@tonic-gate if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR) 590*0Sstevel@tonic-gate return (CTF_ERR); /* errno is set for us */ 591*0Sstevel@tonic-gate 592*0Sstevel@tonic-gate dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_ARRAY, flag, 0); 593*0Sstevel@tonic-gate dtd->dtd_data.ctt_size = 0; 594*0Sstevel@tonic-gate dtd->dtd_u.dtu_arr = *arp; 595*0Sstevel@tonic-gate 596*0Sstevel@tonic-gate return (type); 597*0Sstevel@tonic-gate } 598*0Sstevel@tonic-gate 599*0Sstevel@tonic-gate int 600*0Sstevel@tonic-gate ctf_set_array(ctf_file_t *fp, ctf_id_t type, const ctf_arinfo_t *arp) 601*0Sstevel@tonic-gate { 602*0Sstevel@tonic-gate ctf_dtdef_t *dtd; 603*0Sstevel@tonic-gate 604*0Sstevel@tonic-gate if (!(fp->ctf_flags & LCTF_RDWR)) 605*0Sstevel@tonic-gate return (ctf_set_errno(fp, ECTF_RDONLY)); 606*0Sstevel@tonic-gate 607*0Sstevel@tonic-gate for (dtd = ctf_list_next(&fp->ctf_dtdefs); 608*0Sstevel@tonic-gate dtd != NULL; dtd = ctf_list_next(dtd)) { 609*0Sstevel@tonic-gate if (dtd->dtd_type == type) 610*0Sstevel@tonic-gate break; 611*0Sstevel@tonic-gate } 612*0Sstevel@tonic-gate 613*0Sstevel@tonic-gate if (dtd == NULL || CTF_INFO_KIND(dtd->dtd_data.ctt_info) != CTF_K_ARRAY) 614*0Sstevel@tonic-gate return (ctf_set_errno(fp, ECTF_BADID)); 615*0Sstevel@tonic-gate 616*0Sstevel@tonic-gate fp->ctf_flags |= LCTF_DIRTY; 617*0Sstevel@tonic-gate dtd->dtd_u.dtu_arr = *arp; 618*0Sstevel@tonic-gate 619*0Sstevel@tonic-gate return (0); 620*0Sstevel@tonic-gate } 621*0Sstevel@tonic-gate 622*0Sstevel@tonic-gate ctf_id_t 623*0Sstevel@tonic-gate ctf_add_function(ctf_file_t *fp, uint_t flag, 624*0Sstevel@tonic-gate const ctf_funcinfo_t *ctc, const ctf_id_t *argv) 625*0Sstevel@tonic-gate { 626*0Sstevel@tonic-gate ctf_dtdef_t *dtd; 627*0Sstevel@tonic-gate ctf_id_t type; 628*0Sstevel@tonic-gate uint_t vlen; 629*0Sstevel@tonic-gate ctf_id_t *vdat = NULL; 630*0Sstevel@tonic-gate 631*0Sstevel@tonic-gate if (ctc == NULL || (ctc->ctc_flags & ~CTF_FUNC_VARARG) != 0 || 632*0Sstevel@tonic-gate (ctc->ctc_argc != 0 && argv == NULL)) 633*0Sstevel@tonic-gate return (ctf_set_errno(fp, EINVAL)); 634*0Sstevel@tonic-gate 635*0Sstevel@tonic-gate vlen = ctc->ctc_argc; 636*0Sstevel@tonic-gate if (ctc->ctc_flags & CTF_FUNC_VARARG) 637*0Sstevel@tonic-gate vlen++; /* add trailing zero to indicate varargs (see below) */ 638*0Sstevel@tonic-gate 639*0Sstevel@tonic-gate if (vlen > CTF_MAX_VLEN) 640*0Sstevel@tonic-gate return (ctf_set_errno(fp, EOVERFLOW)); 641*0Sstevel@tonic-gate 642*0Sstevel@tonic-gate if (vlen != 0 && (vdat = ctf_alloc(sizeof (ctf_id_t) * vlen)) == NULL) 643*0Sstevel@tonic-gate return (ctf_set_errno(fp, EAGAIN)); 644*0Sstevel@tonic-gate 645*0Sstevel@tonic-gate if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR) { 646*0Sstevel@tonic-gate ctf_free(vdat, sizeof (ctf_id_t) * vlen); 647*0Sstevel@tonic-gate return (CTF_ERR); /* errno is set for us */ 648*0Sstevel@tonic-gate } 649*0Sstevel@tonic-gate 650*0Sstevel@tonic-gate dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_FUNCTION, flag, vlen); 651*0Sstevel@tonic-gate dtd->dtd_data.ctt_type = (ushort_t)ctc->ctc_return; 652*0Sstevel@tonic-gate 653*0Sstevel@tonic-gate bcopy(argv, vdat, sizeof (ctf_id_t) * ctc->ctc_argc); 654*0Sstevel@tonic-gate if (ctc->ctc_flags & CTF_FUNC_VARARG) 655*0Sstevel@tonic-gate vdat[vlen - 1] = 0; /* add trailing zero to indicate varargs */ 656*0Sstevel@tonic-gate dtd->dtd_u.dtu_argv = vdat; 657*0Sstevel@tonic-gate 658*0Sstevel@tonic-gate return (type); 659*0Sstevel@tonic-gate } 660*0Sstevel@tonic-gate 661*0Sstevel@tonic-gate ctf_id_t 662*0Sstevel@tonic-gate ctf_add_struct(ctf_file_t *fp, uint_t flag, const char *name) 663*0Sstevel@tonic-gate { 664*0Sstevel@tonic-gate ctf_dtdef_t *dtd; 665*0Sstevel@tonic-gate ctf_id_t type; 666*0Sstevel@tonic-gate 667*0Sstevel@tonic-gate if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR) 668*0Sstevel@tonic-gate return (CTF_ERR); /* errno is set for us */ 669*0Sstevel@tonic-gate 670*0Sstevel@tonic-gate dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_STRUCT, flag, 0); 671*0Sstevel@tonic-gate return (type); 672*0Sstevel@tonic-gate } 673*0Sstevel@tonic-gate 674*0Sstevel@tonic-gate ctf_id_t 675*0Sstevel@tonic-gate ctf_add_union(ctf_file_t *fp, uint_t flag, const char *name) 676*0Sstevel@tonic-gate { 677*0Sstevel@tonic-gate ctf_dtdef_t *dtd; 678*0Sstevel@tonic-gate ctf_id_t type; 679*0Sstevel@tonic-gate 680*0Sstevel@tonic-gate if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR) 681*0Sstevel@tonic-gate return (CTF_ERR); /* errno is set for us */ 682*0Sstevel@tonic-gate 683*0Sstevel@tonic-gate dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_UNION, flag, 0); 684*0Sstevel@tonic-gate return (type); 685*0Sstevel@tonic-gate } 686*0Sstevel@tonic-gate 687*0Sstevel@tonic-gate ctf_id_t 688*0Sstevel@tonic-gate ctf_add_enum(ctf_file_t *fp, uint_t flag, const char *name) 689*0Sstevel@tonic-gate { 690*0Sstevel@tonic-gate ctf_dtdef_t *dtd; 691*0Sstevel@tonic-gate ctf_id_t type; 692*0Sstevel@tonic-gate 693*0Sstevel@tonic-gate if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR) 694*0Sstevel@tonic-gate return (CTF_ERR); /* errno is set for us */ 695*0Sstevel@tonic-gate 696*0Sstevel@tonic-gate dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_ENUM, flag, 0); 697*0Sstevel@tonic-gate dtd->dtd_data.ctt_size = fp->ctf_dmodel->ctd_int; 698*0Sstevel@tonic-gate 699*0Sstevel@tonic-gate return (type); 700*0Sstevel@tonic-gate } 701*0Sstevel@tonic-gate 702*0Sstevel@tonic-gate ctf_id_t 703*0Sstevel@tonic-gate ctf_add_forward(ctf_file_t *fp, uint_t flag, const char *name, uint_t kind) 704*0Sstevel@tonic-gate { 705*0Sstevel@tonic-gate ctf_dtdef_t *dtd; 706*0Sstevel@tonic-gate ctf_id_t type; 707*0Sstevel@tonic-gate 708*0Sstevel@tonic-gate if (kind != CTF_K_STRUCT && kind != CTF_K_UNION && kind != CTF_K_ENUM) 709*0Sstevel@tonic-gate return (ctf_set_errno(fp, ECTF_NOTSUE)); 710*0Sstevel@tonic-gate 711*0Sstevel@tonic-gate if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR) 712*0Sstevel@tonic-gate return (CTF_ERR); /* errno is set for us */ 713*0Sstevel@tonic-gate 714*0Sstevel@tonic-gate dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_FORWARD, flag, 0); 715*0Sstevel@tonic-gate return (type); 716*0Sstevel@tonic-gate } 717*0Sstevel@tonic-gate 718*0Sstevel@tonic-gate ctf_id_t 719*0Sstevel@tonic-gate ctf_add_typedef(ctf_file_t *fp, uint_t flag, const char *name, ctf_id_t ref) 720*0Sstevel@tonic-gate { 721*0Sstevel@tonic-gate ctf_dtdef_t *dtd; 722*0Sstevel@tonic-gate ctf_id_t type; 723*0Sstevel@tonic-gate 724*0Sstevel@tonic-gate if (ref == CTF_ERR || ref < 0 || ref > CTF_MAX_TYPE) 725*0Sstevel@tonic-gate return (ctf_set_errno(fp, EINVAL)); 726*0Sstevel@tonic-gate 727*0Sstevel@tonic-gate if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR) 728*0Sstevel@tonic-gate return (CTF_ERR); /* errno is set for us */ 729*0Sstevel@tonic-gate 730*0Sstevel@tonic-gate dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_TYPEDEF, flag, 0); 731*0Sstevel@tonic-gate dtd->dtd_data.ctt_type = (ushort_t)ref; 732*0Sstevel@tonic-gate 733*0Sstevel@tonic-gate return (type); 734*0Sstevel@tonic-gate } 735*0Sstevel@tonic-gate 736*0Sstevel@tonic-gate ctf_id_t 737*0Sstevel@tonic-gate ctf_add_volatile(ctf_file_t *fp, uint_t flag, ctf_id_t ref) 738*0Sstevel@tonic-gate { 739*0Sstevel@tonic-gate return (ctf_add_reftype(fp, flag, ref, CTF_K_VOLATILE)); 740*0Sstevel@tonic-gate } 741*0Sstevel@tonic-gate 742*0Sstevel@tonic-gate ctf_id_t 743*0Sstevel@tonic-gate ctf_add_const(ctf_file_t *fp, uint_t flag, ctf_id_t ref) 744*0Sstevel@tonic-gate { 745*0Sstevel@tonic-gate return (ctf_add_reftype(fp, flag, ref, CTF_K_CONST)); 746*0Sstevel@tonic-gate } 747*0Sstevel@tonic-gate 748*0Sstevel@tonic-gate ctf_id_t 749*0Sstevel@tonic-gate ctf_add_restrict(ctf_file_t *fp, uint_t flag, ctf_id_t ref) 750*0Sstevel@tonic-gate { 751*0Sstevel@tonic-gate return (ctf_add_reftype(fp, flag, ref, CTF_K_RESTRICT)); 752*0Sstevel@tonic-gate } 753*0Sstevel@tonic-gate 754*0Sstevel@tonic-gate int 755*0Sstevel@tonic-gate ctf_add_enumerator(ctf_file_t *fp, ctf_id_t enid, const char *name, int value) 756*0Sstevel@tonic-gate { 757*0Sstevel@tonic-gate ctf_dtdef_t *dtd; 758*0Sstevel@tonic-gate ctf_dmdef_t *dmd; 759*0Sstevel@tonic-gate 760*0Sstevel@tonic-gate uint_t kind, vlen, root; 761*0Sstevel@tonic-gate char *s; 762*0Sstevel@tonic-gate 763*0Sstevel@tonic-gate if (name == NULL) 764*0Sstevel@tonic-gate return (ctf_set_errno(fp, EINVAL)); 765*0Sstevel@tonic-gate 766*0Sstevel@tonic-gate if (!(fp->ctf_flags & LCTF_RDWR)) 767*0Sstevel@tonic-gate return (ctf_set_errno(fp, ECTF_RDONLY)); 768*0Sstevel@tonic-gate 769*0Sstevel@tonic-gate for (dtd = ctf_list_next(&fp->ctf_dtdefs); 770*0Sstevel@tonic-gate dtd != NULL; dtd = ctf_list_next(dtd)) { 771*0Sstevel@tonic-gate if (dtd->dtd_type == enid) 772*0Sstevel@tonic-gate break; 773*0Sstevel@tonic-gate } 774*0Sstevel@tonic-gate 775*0Sstevel@tonic-gate if (dtd == NULL) 776*0Sstevel@tonic-gate return (ctf_set_errno(fp, ECTF_BADID)); 777*0Sstevel@tonic-gate 778*0Sstevel@tonic-gate kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info); 779*0Sstevel@tonic-gate root = CTF_INFO_ISROOT(dtd->dtd_data.ctt_info); 780*0Sstevel@tonic-gate vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info); 781*0Sstevel@tonic-gate 782*0Sstevel@tonic-gate if (kind != CTF_K_ENUM) 783*0Sstevel@tonic-gate return (ctf_set_errno(fp, ECTF_NOTENUM)); 784*0Sstevel@tonic-gate 785*0Sstevel@tonic-gate if (vlen == CTF_MAX_VLEN) 786*0Sstevel@tonic-gate return (ctf_set_errno(fp, ECTF_DTFULL)); 787*0Sstevel@tonic-gate 788*0Sstevel@tonic-gate for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members); 789*0Sstevel@tonic-gate dmd != NULL; dmd = ctf_list_next(dmd)) { 790*0Sstevel@tonic-gate if (strcmp(dmd->dmd_name, name) == 0) 791*0Sstevel@tonic-gate return (ctf_set_errno(fp, ECTF_DUPMEMBER)); 792*0Sstevel@tonic-gate } 793*0Sstevel@tonic-gate 794*0Sstevel@tonic-gate if ((dmd = ctf_alloc(sizeof (ctf_dmdef_t))) == NULL) 795*0Sstevel@tonic-gate return (ctf_set_errno(fp, EAGAIN)); 796*0Sstevel@tonic-gate 797*0Sstevel@tonic-gate if ((s = ctf_strdup(name)) == NULL) { 798*0Sstevel@tonic-gate ctf_free(dmd, sizeof (ctf_dmdef_t)); 799*0Sstevel@tonic-gate return (ctf_set_errno(fp, EAGAIN)); 800*0Sstevel@tonic-gate } 801*0Sstevel@tonic-gate 802*0Sstevel@tonic-gate dmd->dmd_name = s; 803*0Sstevel@tonic-gate dmd->dmd_type = CTF_ERR; 804*0Sstevel@tonic-gate dmd->dmd_offset = 0; 805*0Sstevel@tonic-gate dmd->dmd_value = value; 806*0Sstevel@tonic-gate 807*0Sstevel@tonic-gate dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, root, vlen + 1); 808*0Sstevel@tonic-gate ctf_list_append(&dtd->dtd_u.dtu_members, dmd); 809*0Sstevel@tonic-gate 810*0Sstevel@tonic-gate fp->ctf_dtstrlen += strlen(s) + 1; 811*0Sstevel@tonic-gate fp->ctf_flags |= LCTF_DIRTY; 812*0Sstevel@tonic-gate 813*0Sstevel@tonic-gate return (0); 814*0Sstevel@tonic-gate } 815*0Sstevel@tonic-gate 816*0Sstevel@tonic-gate int 817*0Sstevel@tonic-gate ctf_add_member(ctf_file_t *fp, ctf_id_t souid, const char *name, ctf_id_t type) 818*0Sstevel@tonic-gate { 819*0Sstevel@tonic-gate ctf_dtdef_t *dtd; 820*0Sstevel@tonic-gate ctf_dmdef_t *dmd; 821*0Sstevel@tonic-gate 822*0Sstevel@tonic-gate ssize_t msize, malign, ssize; 823*0Sstevel@tonic-gate uint_t kind, vlen, root; 824*0Sstevel@tonic-gate char *s = NULL; 825*0Sstevel@tonic-gate 826*0Sstevel@tonic-gate if (!(fp->ctf_flags & LCTF_RDWR)) 827*0Sstevel@tonic-gate return (ctf_set_errno(fp, ECTF_RDONLY)); 828*0Sstevel@tonic-gate 829*0Sstevel@tonic-gate for (dtd = ctf_list_next(&fp->ctf_dtdefs); 830*0Sstevel@tonic-gate dtd != NULL; dtd = ctf_list_next(dtd)) { 831*0Sstevel@tonic-gate if (dtd->dtd_type == souid) 832*0Sstevel@tonic-gate break; 833*0Sstevel@tonic-gate } 834*0Sstevel@tonic-gate 835*0Sstevel@tonic-gate if (dtd == NULL) 836*0Sstevel@tonic-gate return (ctf_set_errno(fp, ECTF_BADID)); 837*0Sstevel@tonic-gate 838*0Sstevel@tonic-gate kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info); 839*0Sstevel@tonic-gate root = CTF_INFO_ISROOT(dtd->dtd_data.ctt_info); 840*0Sstevel@tonic-gate vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info); 841*0Sstevel@tonic-gate 842*0Sstevel@tonic-gate if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) 843*0Sstevel@tonic-gate return (ctf_set_errno(fp, ECTF_NOTSOU)); 844*0Sstevel@tonic-gate 845*0Sstevel@tonic-gate if (vlen == CTF_MAX_VLEN) 846*0Sstevel@tonic-gate return (ctf_set_errno(fp, ECTF_DTFULL)); 847*0Sstevel@tonic-gate 848*0Sstevel@tonic-gate if (name != NULL) { 849*0Sstevel@tonic-gate for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members); 850*0Sstevel@tonic-gate dmd != NULL; dmd = ctf_list_next(dmd)) { 851*0Sstevel@tonic-gate if (dmd->dmd_name != NULL && 852*0Sstevel@tonic-gate strcmp(dmd->dmd_name, name) == 0) 853*0Sstevel@tonic-gate return (ctf_set_errno(fp, ECTF_DUPMEMBER)); 854*0Sstevel@tonic-gate } 855*0Sstevel@tonic-gate } 856*0Sstevel@tonic-gate 857*0Sstevel@tonic-gate if ((msize = ctf_type_size(fp, type)) == CTF_ERR || 858*0Sstevel@tonic-gate (malign = ctf_type_align(fp, type)) == CTF_ERR) 859*0Sstevel@tonic-gate return (CTF_ERR); /* errno is set for us */ 860*0Sstevel@tonic-gate 861*0Sstevel@tonic-gate if ((dmd = ctf_alloc(sizeof (ctf_dmdef_t))) == NULL) 862*0Sstevel@tonic-gate return (ctf_set_errno(fp, EAGAIN)); 863*0Sstevel@tonic-gate 864*0Sstevel@tonic-gate if (name != NULL && (s = ctf_strdup(name)) == NULL) { 865*0Sstevel@tonic-gate ctf_free(dmd, sizeof (ctf_dmdef_t)); 866*0Sstevel@tonic-gate return (ctf_set_errno(fp, EAGAIN)); 867*0Sstevel@tonic-gate } 868*0Sstevel@tonic-gate 869*0Sstevel@tonic-gate dmd->dmd_name = s; 870*0Sstevel@tonic-gate dmd->dmd_type = type; 871*0Sstevel@tonic-gate dmd->dmd_value = -1; 872*0Sstevel@tonic-gate 873*0Sstevel@tonic-gate if (kind == CTF_K_STRUCT && vlen != 0) { 874*0Sstevel@tonic-gate ctf_dmdef_t *lmd = ctf_list_prev(&dtd->dtd_u.dtu_members); 875*0Sstevel@tonic-gate ctf_id_t ltype = ctf_type_resolve(fp, lmd->dmd_type); 876*0Sstevel@tonic-gate size_t off = lmd->dmd_offset; 877*0Sstevel@tonic-gate 878*0Sstevel@tonic-gate ctf_encoding_t linfo; 879*0Sstevel@tonic-gate ssize_t lsize; 880*0Sstevel@tonic-gate 881*0Sstevel@tonic-gate if (ctf_type_encoding(fp, ltype, &linfo) != CTF_ERR) 882*0Sstevel@tonic-gate off += linfo.cte_bits; 883*0Sstevel@tonic-gate else if ((lsize = ctf_type_size(fp, ltype)) != CTF_ERR) 884*0Sstevel@tonic-gate off += lsize * NBBY; 885*0Sstevel@tonic-gate 886*0Sstevel@tonic-gate /* 887*0Sstevel@tonic-gate * Round up the offset of the end of the last member to the 888*0Sstevel@tonic-gate * next byte boundary, convert 'off' to bytes, and then round 889*0Sstevel@tonic-gate * it up again to the next multiple of the alignment required 890*0Sstevel@tonic-gate * by the new member. Finally, convert back to bits and store 891*0Sstevel@tonic-gate * the result in dmd_offset. Technically we could do more 892*0Sstevel@tonic-gate * efficient packing if the new member is a bit-field, but 893*0Sstevel@tonic-gate * we're the "compiler" and ANSI says we can do as we choose. 894*0Sstevel@tonic-gate */ 895*0Sstevel@tonic-gate off = roundup(off, NBBY) / NBBY; 896*0Sstevel@tonic-gate off = roundup(off, MAX(malign, 1)); 897*0Sstevel@tonic-gate dmd->dmd_offset = off * NBBY; 898*0Sstevel@tonic-gate ssize = off + msize; 899*0Sstevel@tonic-gate } else { 900*0Sstevel@tonic-gate dmd->dmd_offset = 0; 901*0Sstevel@tonic-gate ssize = ctf_get_ctt_size(fp, &dtd->dtd_data, NULL, NULL); 902*0Sstevel@tonic-gate ssize = MAX(ssize, msize); 903*0Sstevel@tonic-gate } 904*0Sstevel@tonic-gate 905*0Sstevel@tonic-gate if (ssize > CTF_MAX_SIZE) { 906*0Sstevel@tonic-gate dtd->dtd_data.ctt_size = CTF_LSIZE_SENT; 907*0Sstevel@tonic-gate dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(ssize); 908*0Sstevel@tonic-gate dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(ssize); 909*0Sstevel@tonic-gate } else 910*0Sstevel@tonic-gate dtd->dtd_data.ctt_size = (ushort_t)ssize; 911*0Sstevel@tonic-gate 912*0Sstevel@tonic-gate dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, root, vlen + 1); 913*0Sstevel@tonic-gate ctf_list_append(&dtd->dtd_u.dtu_members, dmd); 914*0Sstevel@tonic-gate 915*0Sstevel@tonic-gate if (s != NULL) 916*0Sstevel@tonic-gate fp->ctf_dtstrlen += strlen(s) + 1; 917*0Sstevel@tonic-gate 918*0Sstevel@tonic-gate fp->ctf_flags |= LCTF_DIRTY; 919*0Sstevel@tonic-gate return (0); 920*0Sstevel@tonic-gate } 921*0Sstevel@tonic-gate 922*0Sstevel@tonic-gate static int 923*0Sstevel@tonic-gate enumcmp(const char *name, int value, void *arg) 924*0Sstevel@tonic-gate { 925*0Sstevel@tonic-gate ctf_bundle_t *ctb = arg; 926*0Sstevel@tonic-gate int bvalue; 927*0Sstevel@tonic-gate 928*0Sstevel@tonic-gate return (ctf_enum_value(ctb->ctb_file, ctb->ctb_type, 929*0Sstevel@tonic-gate name, &bvalue) == CTF_ERR || value != bvalue); 930*0Sstevel@tonic-gate } 931*0Sstevel@tonic-gate 932*0Sstevel@tonic-gate static int 933*0Sstevel@tonic-gate enumadd(const char *name, int value, void *arg) 934*0Sstevel@tonic-gate { 935*0Sstevel@tonic-gate ctf_bundle_t *ctb = arg; 936*0Sstevel@tonic-gate 937*0Sstevel@tonic-gate return (ctf_add_enumerator(ctb->ctb_file, ctb->ctb_type, 938*0Sstevel@tonic-gate name, value) == CTF_ERR); 939*0Sstevel@tonic-gate } 940*0Sstevel@tonic-gate 941*0Sstevel@tonic-gate /*ARGSUSED*/ 942*0Sstevel@tonic-gate static int 943*0Sstevel@tonic-gate membcmp(const char *name, ctf_id_t type, ulong_t offset, void *arg) 944*0Sstevel@tonic-gate { 945*0Sstevel@tonic-gate ctf_bundle_t *ctb = arg; 946*0Sstevel@tonic-gate ctf_membinfo_t ctm; 947*0Sstevel@tonic-gate 948*0Sstevel@tonic-gate return (ctf_member_info(ctb->ctb_file, ctb->ctb_type, 949*0Sstevel@tonic-gate name, &ctm) == CTF_ERR || ctm.ctm_offset != offset); 950*0Sstevel@tonic-gate } 951*0Sstevel@tonic-gate 952*0Sstevel@tonic-gate static int 953*0Sstevel@tonic-gate membadd(const char *name, ctf_id_t type, ulong_t offset, void *arg) 954*0Sstevel@tonic-gate { 955*0Sstevel@tonic-gate ctf_bundle_t *ctb = arg; 956*0Sstevel@tonic-gate ctf_dmdef_t *dmd; 957*0Sstevel@tonic-gate char *s = NULL; 958*0Sstevel@tonic-gate 959*0Sstevel@tonic-gate if ((dmd = ctf_alloc(sizeof (ctf_dmdef_t))) == NULL) 960*0Sstevel@tonic-gate return (ctf_set_errno(ctb->ctb_file, EAGAIN)); 961*0Sstevel@tonic-gate 962*0Sstevel@tonic-gate if (name != NULL && (s = ctf_strdup(name)) == NULL) { 963*0Sstevel@tonic-gate ctf_free(dmd, sizeof (ctf_dmdef_t)); 964*0Sstevel@tonic-gate return (ctf_set_errno(ctb->ctb_file, EAGAIN)); 965*0Sstevel@tonic-gate } 966*0Sstevel@tonic-gate 967*0Sstevel@tonic-gate /* 968*0Sstevel@tonic-gate * For now, dmd_type is copied as the src_fp's type; it is reset to an 969*0Sstevel@tonic-gate * equivalent dst_fp type by a final loop in ctf_add_type(), below. 970*0Sstevel@tonic-gate */ 971*0Sstevel@tonic-gate dmd->dmd_name = s; 972*0Sstevel@tonic-gate dmd->dmd_type = type; 973*0Sstevel@tonic-gate dmd->dmd_offset = offset; 974*0Sstevel@tonic-gate dmd->dmd_value = -1; 975*0Sstevel@tonic-gate 976*0Sstevel@tonic-gate ctf_list_append(&ctb->ctb_dtd->dtd_u.dtu_members, dmd); 977*0Sstevel@tonic-gate 978*0Sstevel@tonic-gate if (s != NULL) 979*0Sstevel@tonic-gate ctb->ctb_file->ctf_dtstrlen += strlen(s) + 1; 980*0Sstevel@tonic-gate 981*0Sstevel@tonic-gate ctb->ctb_file->ctf_flags |= LCTF_DIRTY; 982*0Sstevel@tonic-gate return (0); 983*0Sstevel@tonic-gate } 984*0Sstevel@tonic-gate 985*0Sstevel@tonic-gate /* 986*0Sstevel@tonic-gate * The ctf_add_type routine is used to copy a type from a source CTF container 987*0Sstevel@tonic-gate * to a dynamic destination container. This routine operates recursively by 988*0Sstevel@tonic-gate * following the source type's links and embedded member types. If the 989*0Sstevel@tonic-gate * destination container already contains a named type which has the same 990*0Sstevel@tonic-gate * attributes, then we succeed and return this type but no changes occur. 991*0Sstevel@tonic-gate */ 992*0Sstevel@tonic-gate ctf_id_t 993*0Sstevel@tonic-gate ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) 994*0Sstevel@tonic-gate { 995*0Sstevel@tonic-gate ctf_id_t dst_type = CTF_ERR; 996*0Sstevel@tonic-gate uint_t dst_kind = CTF_K_UNKNOWN; 997*0Sstevel@tonic-gate 998*0Sstevel@tonic-gate const ctf_type_t *tp; 999*0Sstevel@tonic-gate const char *name; 1000*0Sstevel@tonic-gate uint_t kind, flag, vlen; 1001*0Sstevel@tonic-gate 1002*0Sstevel@tonic-gate ctf_bundle_t src, dst; 1003*0Sstevel@tonic-gate ctf_encoding_t src_en, dst_en; 1004*0Sstevel@tonic-gate ctf_arinfo_t src_ar, dst_ar; 1005*0Sstevel@tonic-gate 1006*0Sstevel@tonic-gate ctf_dtdef_t *dtd; 1007*0Sstevel@tonic-gate ctf_funcinfo_t ctc; 1008*0Sstevel@tonic-gate ssize_t size; 1009*0Sstevel@tonic-gate 1010*0Sstevel@tonic-gate ctf_hash_t *hp; 1011*0Sstevel@tonic-gate ctf_helem_t *hep; 1012*0Sstevel@tonic-gate 1013*0Sstevel@tonic-gate if (!(dst_fp->ctf_flags & LCTF_RDWR)) 1014*0Sstevel@tonic-gate return (ctf_set_errno(dst_fp, ECTF_RDONLY)); 1015*0Sstevel@tonic-gate 1016*0Sstevel@tonic-gate if ((tp = ctf_lookup_by_id(&src_fp, src_type)) == NULL) 1017*0Sstevel@tonic-gate return (ctf_set_errno(dst_fp, ctf_errno(src_fp))); 1018*0Sstevel@tonic-gate 1019*0Sstevel@tonic-gate name = ctf_strptr(src_fp, tp->ctt_name); 1020*0Sstevel@tonic-gate kind = LCTF_INFO_KIND(src_fp, tp->ctt_info); 1021*0Sstevel@tonic-gate flag = LCTF_INFO_ROOT(src_fp, tp->ctt_info); 1022*0Sstevel@tonic-gate vlen = LCTF_INFO_VLEN(src_fp, tp->ctt_info); 1023*0Sstevel@tonic-gate 1024*0Sstevel@tonic-gate switch (kind) { 1025*0Sstevel@tonic-gate case CTF_K_STRUCT: 1026*0Sstevel@tonic-gate hp = &dst_fp->ctf_structs; 1027*0Sstevel@tonic-gate break; 1028*0Sstevel@tonic-gate case CTF_K_UNION: 1029*0Sstevel@tonic-gate hp = &dst_fp->ctf_unions; 1030*0Sstevel@tonic-gate break; 1031*0Sstevel@tonic-gate case CTF_K_ENUM: 1032*0Sstevel@tonic-gate hp = &dst_fp->ctf_enums; 1033*0Sstevel@tonic-gate break; 1034*0Sstevel@tonic-gate default: 1035*0Sstevel@tonic-gate hp = &dst_fp->ctf_names; 1036*0Sstevel@tonic-gate break; 1037*0Sstevel@tonic-gate } 1038*0Sstevel@tonic-gate 1039*0Sstevel@tonic-gate /* 1040*0Sstevel@tonic-gate * If the source type has a name and is a root type (visible at the 1041*0Sstevel@tonic-gate * top-level scope), lookup the name in the destination container and 1042*0Sstevel@tonic-gate * verify that it is of the same kind before we do anything else. 1043*0Sstevel@tonic-gate */ 1044*0Sstevel@tonic-gate if ((flag & CTF_ADD_ROOT) && name[0] != '\0' && 1045*0Sstevel@tonic-gate (hep = ctf_hash_lookup(hp, dst_fp, name, strlen(name))) != NULL) { 1046*0Sstevel@tonic-gate dst_type = (ctf_id_t)hep->h_type; 1047*0Sstevel@tonic-gate dst_kind = ctf_type_kind(dst_fp, dst_type); 1048*0Sstevel@tonic-gate } 1049*0Sstevel@tonic-gate 1050*0Sstevel@tonic-gate /* 1051*0Sstevel@tonic-gate * If an identically named dst_type exists, fail with ECTF_CONFLICT 1052*0Sstevel@tonic-gate * unless dst_type is a forward declaration and src_type is a struct, 1053*0Sstevel@tonic-gate * union, or enum (i.e. the definition of the previous forward decl). 1054*0Sstevel@tonic-gate */ 1055*0Sstevel@tonic-gate if (dst_type != CTF_ERR && dst_kind != kind && ( 1056*0Sstevel@tonic-gate dst_kind != CTF_K_FORWARD || (kind != CTF_K_ENUM && 1057*0Sstevel@tonic-gate kind != CTF_K_STRUCT && kind != CTF_K_UNION))) 1058*0Sstevel@tonic-gate return (ctf_set_errno(dst_fp, ECTF_CONFLICT)); 1059*0Sstevel@tonic-gate 1060*0Sstevel@tonic-gate /* 1061*0Sstevel@tonic-gate * If the non-empty name was not found in the appropriate hash, search 1062*0Sstevel@tonic-gate * the list of pending dynamic definitions that are not yet committed. 1063*0Sstevel@tonic-gate * If a matching name and kind are found, assume this is the type that 1064*0Sstevel@tonic-gate * we are looking for. This is necessary to permit ctf_add_type() to 1065*0Sstevel@tonic-gate * operate recursively on entities such as a struct that contains a 1066*0Sstevel@tonic-gate * pointer member that refers to the same struct type. 1067*0Sstevel@tonic-gate */ 1068*0Sstevel@tonic-gate if (dst_type == CTF_ERR && name[0] != '\0') { 1069*0Sstevel@tonic-gate for (dtd = ctf_list_prev(&dst_fp->ctf_dtdefs); dtd != NULL && 1070*0Sstevel@tonic-gate dtd->dtd_type > dst_fp->ctf_dtoldid; 1071*0Sstevel@tonic-gate dtd = ctf_list_prev(dtd)) { 1072*0Sstevel@tonic-gate if (CTF_INFO_KIND(dtd->dtd_data.ctt_info) == kind && 1073*0Sstevel@tonic-gate dtd->dtd_name != NULL && 1074*0Sstevel@tonic-gate strcmp(dtd->dtd_name, name) == 0) 1075*0Sstevel@tonic-gate return (dtd->dtd_type); 1076*0Sstevel@tonic-gate } 1077*0Sstevel@tonic-gate } 1078*0Sstevel@tonic-gate 1079*0Sstevel@tonic-gate src.ctb_file = src_fp; 1080*0Sstevel@tonic-gate src.ctb_type = src_type; 1081*0Sstevel@tonic-gate src.ctb_dtd = NULL; 1082*0Sstevel@tonic-gate 1083*0Sstevel@tonic-gate dst.ctb_file = dst_fp; 1084*0Sstevel@tonic-gate dst.ctb_type = dst_type; 1085*0Sstevel@tonic-gate dst.ctb_dtd = NULL; 1086*0Sstevel@tonic-gate 1087*0Sstevel@tonic-gate /* 1088*0Sstevel@tonic-gate * Now perform kind-specific processing. If dst_type is CTF_ERR, then 1089*0Sstevel@tonic-gate * we add a new type with the same properties as src_type to dst_fp. 1090*0Sstevel@tonic-gate * If dst_type is not CTF_ERR, then we verify that dst_type has the 1091*0Sstevel@tonic-gate * same attributes as src_type. We recurse for embedded references. 1092*0Sstevel@tonic-gate */ 1093*0Sstevel@tonic-gate switch (kind) { 1094*0Sstevel@tonic-gate case CTF_K_INTEGER: 1095*0Sstevel@tonic-gate case CTF_K_FLOAT: 1096*0Sstevel@tonic-gate if (ctf_type_encoding(src_fp, src_type, &src_en) != 0) 1097*0Sstevel@tonic-gate return (ctf_set_errno(dst_fp, ctf_errno(src_fp))); 1098*0Sstevel@tonic-gate 1099*0Sstevel@tonic-gate if (dst_type != CTF_ERR) { 1100*0Sstevel@tonic-gate if (ctf_type_encoding(dst_fp, dst_type, &dst_en) != 0) 1101*0Sstevel@tonic-gate return (CTF_ERR); /* errno is set for us */ 1102*0Sstevel@tonic-gate 1103*0Sstevel@tonic-gate if (bcmp(&src_en, &dst_en, sizeof (ctf_encoding_t))) 1104*0Sstevel@tonic-gate return (ctf_set_errno(dst_fp, ECTF_CONFLICT)); 1105*0Sstevel@tonic-gate 1106*0Sstevel@tonic-gate } else if (kind == CTF_K_INTEGER) { 1107*0Sstevel@tonic-gate dst_type = ctf_add_integer(dst_fp, flag, name, &src_en); 1108*0Sstevel@tonic-gate } else 1109*0Sstevel@tonic-gate dst_type = ctf_add_float(dst_fp, flag, name, &src_en); 1110*0Sstevel@tonic-gate break; 1111*0Sstevel@tonic-gate 1112*0Sstevel@tonic-gate case CTF_K_POINTER: 1113*0Sstevel@tonic-gate case CTF_K_VOLATILE: 1114*0Sstevel@tonic-gate case CTF_K_CONST: 1115*0Sstevel@tonic-gate case CTF_K_RESTRICT: 1116*0Sstevel@tonic-gate src_type = ctf_type_reference(src_fp, src_type); 1117*0Sstevel@tonic-gate src_type = ctf_add_type(dst_fp, src_fp, src_type); 1118*0Sstevel@tonic-gate 1119*0Sstevel@tonic-gate if (src_type == CTF_ERR) 1120*0Sstevel@tonic-gate return (CTF_ERR); /* errno is set for us */ 1121*0Sstevel@tonic-gate 1122*0Sstevel@tonic-gate dst_type = ctf_add_reftype(dst_fp, flag, src_type, kind); 1123*0Sstevel@tonic-gate break; 1124*0Sstevel@tonic-gate 1125*0Sstevel@tonic-gate case CTF_K_ARRAY: 1126*0Sstevel@tonic-gate if (ctf_array_info(src_fp, src_type, &src_ar) == CTF_ERR) 1127*0Sstevel@tonic-gate return (ctf_set_errno(dst_fp, ctf_errno(src_fp))); 1128*0Sstevel@tonic-gate 1129*0Sstevel@tonic-gate src_ar.ctr_contents = 1130*0Sstevel@tonic-gate ctf_add_type(dst_fp, src_fp, src_ar.ctr_contents); 1131*0Sstevel@tonic-gate src_ar.ctr_index = 1132*0Sstevel@tonic-gate ctf_add_type(dst_fp, src_fp, src_ar.ctr_index); 1133*0Sstevel@tonic-gate src_ar.ctr_nelems = src_ar.ctr_nelems; 1134*0Sstevel@tonic-gate 1135*0Sstevel@tonic-gate if (src_ar.ctr_contents == CTF_ERR || 1136*0Sstevel@tonic-gate src_ar.ctr_index == CTF_ERR) 1137*0Sstevel@tonic-gate return (CTF_ERR); /* errno is set for us */ 1138*0Sstevel@tonic-gate 1139*0Sstevel@tonic-gate if (dst_type != CTF_ERR) { 1140*0Sstevel@tonic-gate if (ctf_array_info(dst_fp, dst_type, &dst_ar) != 0) 1141*0Sstevel@tonic-gate return (CTF_ERR); /* errno is set for us */ 1142*0Sstevel@tonic-gate 1143*0Sstevel@tonic-gate if (bcmp(&src_ar, &dst_ar, sizeof (ctf_arinfo_t))) 1144*0Sstevel@tonic-gate return (ctf_set_errno(dst_fp, ECTF_CONFLICT)); 1145*0Sstevel@tonic-gate } else 1146*0Sstevel@tonic-gate dst_type = ctf_add_array(dst_fp, flag, &src_ar); 1147*0Sstevel@tonic-gate break; 1148*0Sstevel@tonic-gate 1149*0Sstevel@tonic-gate case CTF_K_FUNCTION: 1150*0Sstevel@tonic-gate ctc.ctc_return = ctf_add_type(dst_fp, src_fp, tp->ctt_type); 1151*0Sstevel@tonic-gate ctc.ctc_argc = 0; 1152*0Sstevel@tonic-gate ctc.ctc_flags = 0; 1153*0Sstevel@tonic-gate 1154*0Sstevel@tonic-gate if (ctc.ctc_return == CTF_ERR) 1155*0Sstevel@tonic-gate return (CTF_ERR); /* errno is set for us */ 1156*0Sstevel@tonic-gate 1157*0Sstevel@tonic-gate dst_type = ctf_add_function(dst_fp, flag, &ctc, NULL); 1158*0Sstevel@tonic-gate break; 1159*0Sstevel@tonic-gate 1160*0Sstevel@tonic-gate case CTF_K_STRUCT: 1161*0Sstevel@tonic-gate case CTF_K_UNION: { 1162*0Sstevel@tonic-gate ctf_dmdef_t *dmd; 1163*0Sstevel@tonic-gate int errs = 0; 1164*0Sstevel@tonic-gate 1165*0Sstevel@tonic-gate /* 1166*0Sstevel@tonic-gate * Technically to match a struct or union we need to check both 1167*0Sstevel@tonic-gate * ways (src members vs. dst, dst members vs. src) but we make 1168*0Sstevel@tonic-gate * this more optimal by only checking src vs. dst and comparing 1169*0Sstevel@tonic-gate * the total size of the structure (which we must do anyway) 1170*0Sstevel@tonic-gate * which covers the possibility of dst members not in src. 1171*0Sstevel@tonic-gate * This optimization can be defeated for unions, but is so 1172*0Sstevel@tonic-gate * pathological as to render it irrelevant for our purposes. 1173*0Sstevel@tonic-gate */ 1174*0Sstevel@tonic-gate if (dst_type != CTF_ERR && dst_kind != CTF_K_FORWARD) { 1175*0Sstevel@tonic-gate if (ctf_type_size(src_fp, src_type) != 1176*0Sstevel@tonic-gate ctf_type_size(dst_fp, dst_type)) 1177*0Sstevel@tonic-gate return (ctf_set_errno(dst_fp, ECTF_CONFLICT)); 1178*0Sstevel@tonic-gate 1179*0Sstevel@tonic-gate if (ctf_member_iter(src_fp, src_type, membcmp, &dst)) 1180*0Sstevel@tonic-gate return (ctf_set_errno(dst_fp, ECTF_CONFLICT)); 1181*0Sstevel@tonic-gate 1182*0Sstevel@tonic-gate break; 1183*0Sstevel@tonic-gate } 1184*0Sstevel@tonic-gate 1185*0Sstevel@tonic-gate /* 1186*0Sstevel@tonic-gate * Unlike the other cases, copying structs and unions is done 1187*0Sstevel@tonic-gate * manually so as to avoid repeated lookups in ctf_add_member 1188*0Sstevel@tonic-gate * and to ensure the exact same member offsets as in src_type. 1189*0Sstevel@tonic-gate */ 1190*0Sstevel@tonic-gate dst_type = ctf_add_generic(dst_fp, flag, name, &dtd); 1191*0Sstevel@tonic-gate if (dst_type == CTF_ERR) 1192*0Sstevel@tonic-gate return (CTF_ERR); /* errno is set for us */ 1193*0Sstevel@tonic-gate 1194*0Sstevel@tonic-gate dst.ctb_type = dst_type; 1195*0Sstevel@tonic-gate dst.ctb_dtd = dtd; 1196*0Sstevel@tonic-gate 1197*0Sstevel@tonic-gate if (ctf_member_iter(src_fp, src_type, membadd, &dst) != 0) 1198*0Sstevel@tonic-gate errs++; /* increment errs and fail at bottom of case */ 1199*0Sstevel@tonic-gate 1200*0Sstevel@tonic-gate if ((size = ctf_type_size(src_fp, src_type)) > CTF_MAX_SIZE) { 1201*0Sstevel@tonic-gate dtd->dtd_data.ctt_size = CTF_LSIZE_SENT; 1202*0Sstevel@tonic-gate dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size); 1203*0Sstevel@tonic-gate dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size); 1204*0Sstevel@tonic-gate } else 1205*0Sstevel@tonic-gate dtd->dtd_data.ctt_size = (ushort_t)size; 1206*0Sstevel@tonic-gate 1207*0Sstevel@tonic-gate dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, vlen); 1208*0Sstevel@tonic-gate 1209*0Sstevel@tonic-gate /* 1210*0Sstevel@tonic-gate * Make a final pass through the members changing each dmd_type 1211*0Sstevel@tonic-gate * (a src_fp type) to an equivalent type in dst_fp. We pass 1212*0Sstevel@tonic-gate * through all members, leaving any that fail set to CTF_ERR. 1213*0Sstevel@tonic-gate */ 1214*0Sstevel@tonic-gate for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members); 1215*0Sstevel@tonic-gate dmd != NULL; dmd = ctf_list_next(dmd)) { 1216*0Sstevel@tonic-gate if ((dmd->dmd_type = ctf_add_type(dst_fp, src_fp, 1217*0Sstevel@tonic-gate dmd->dmd_type)) == CTF_ERR) 1218*0Sstevel@tonic-gate errs++; 1219*0Sstevel@tonic-gate } 1220*0Sstevel@tonic-gate 1221*0Sstevel@tonic-gate if (errs) 1222*0Sstevel@tonic-gate return (CTF_ERR); /* errno is set for us */ 1223*0Sstevel@tonic-gate break; 1224*0Sstevel@tonic-gate } 1225*0Sstevel@tonic-gate 1226*0Sstevel@tonic-gate case CTF_K_ENUM: 1227*0Sstevel@tonic-gate if (dst_type != CTF_ERR && dst_kind != CTF_K_FORWARD) { 1228*0Sstevel@tonic-gate if (ctf_enum_iter(src_fp, src_type, enumcmp, &dst) || 1229*0Sstevel@tonic-gate ctf_enum_iter(dst_fp, dst_type, enumcmp, &src)) 1230*0Sstevel@tonic-gate return (ctf_set_errno(dst_fp, ECTF_CONFLICT)); 1231*0Sstevel@tonic-gate } else { 1232*0Sstevel@tonic-gate dst_type = ctf_add_enum(dst_fp, flag, name); 1233*0Sstevel@tonic-gate if ((dst.ctb_type = dst_type) == CTF_ERR || 1234*0Sstevel@tonic-gate ctf_enum_iter(src_fp, src_type, enumadd, &dst)) 1235*0Sstevel@tonic-gate return (CTF_ERR); /* errno is set for us */ 1236*0Sstevel@tonic-gate } 1237*0Sstevel@tonic-gate break; 1238*0Sstevel@tonic-gate 1239*0Sstevel@tonic-gate case CTF_K_FORWARD: 1240*0Sstevel@tonic-gate if (dst_type == CTF_ERR) { 1241*0Sstevel@tonic-gate dst_type = ctf_add_forward(dst_fp, 1242*0Sstevel@tonic-gate flag, name, CTF_K_STRUCT); /* assume STRUCT */ 1243*0Sstevel@tonic-gate } 1244*0Sstevel@tonic-gate break; 1245*0Sstevel@tonic-gate 1246*0Sstevel@tonic-gate case CTF_K_TYPEDEF: 1247*0Sstevel@tonic-gate src_type = ctf_type_reference(src_fp, src_type); 1248*0Sstevel@tonic-gate src_type = ctf_add_type(dst_fp, src_fp, src_type); 1249*0Sstevel@tonic-gate 1250*0Sstevel@tonic-gate if (src_type == CTF_ERR) 1251*0Sstevel@tonic-gate return (CTF_ERR); /* errno is set for us */ 1252*0Sstevel@tonic-gate 1253*0Sstevel@tonic-gate /* 1254*0Sstevel@tonic-gate * If dst_type is not CTF_ERR at this point, we should check if 1255*0Sstevel@tonic-gate * ctf_type_reference(dst_fp, dst_type) != src_type and if so 1256*0Sstevel@tonic-gate * fail with ECTF_CONFLICT. However, this causes problems with 1257*0Sstevel@tonic-gate * <sys/types.h> typedefs that vary based on things like if 1258*0Sstevel@tonic-gate * _ILP32x then pid_t is int otherwise long. We therefore omit 1259*0Sstevel@tonic-gate * this check and assume that if the identically named typedef 1260*0Sstevel@tonic-gate * already exists in dst_fp, it is correct or equivalent. 1261*0Sstevel@tonic-gate */ 1262*0Sstevel@tonic-gate if (dst_type == CTF_ERR) { 1263*0Sstevel@tonic-gate dst_type = ctf_add_typedef(dst_fp, flag, 1264*0Sstevel@tonic-gate name, src_type); 1265*0Sstevel@tonic-gate } 1266*0Sstevel@tonic-gate break; 1267*0Sstevel@tonic-gate 1268*0Sstevel@tonic-gate default: 1269*0Sstevel@tonic-gate return (ctf_set_errno(dst_fp, ECTF_CORRUPT)); 1270*0Sstevel@tonic-gate } 1271*0Sstevel@tonic-gate 1272*0Sstevel@tonic-gate return (dst_type); 1273*0Sstevel@tonic-gate } 1274