Annotation of src/external/gpl3/binutils.old/dist/libctf/ctf-create.c, Revision 1.1
1.1 ! christos 1: /* CTF file creation.
! 2: Copyright (C) 2019-2020 Free Software Foundation, Inc.
! 3:
! 4: This file is part of libctf.
! 5:
! 6: libctf is free software; you can redistribute it and/or modify it under
! 7: the terms of the GNU General Public License as published by the Free
! 8: Software Foundation; either version 3, or (at your option) any later
! 9: version.
! 10:
! 11: This program is distributed in the hope that it will be useful, but
! 12: WITHOUT ANY WARRANTY; without even the implied warranty of
! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
! 14: See the GNU General Public License for more details.
! 15:
! 16: You should have received a copy of the GNU General Public License
! 17: along with this program; see the file COPYING. If not see
! 18: <http://www.gnu.org/licenses/>. */
! 19:
! 20: #include <ctf-impl.h>
! 21: #include <sys/param.h>
! 22: #include <assert.h>
! 23: #include <string.h>
! 24: #include <zlib.h>
! 25:
! 26: #ifndef roundup
! 27: #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
! 28: #endif
! 29:
! 30: /* Make sure the ptrtab has enough space for at least one more type.
! 31:
! 32: We start with 4KiB of ptrtab, enough for a thousand types, then grow it 25%
! 33: at a time. */
! 34:
! 35: static int
! 36: ctf_grow_ptrtab (ctf_file_t *fp)
! 37: {
! 38: size_t new_ptrtab_len = fp->ctf_ptrtab_len;
! 39:
! 40: /* We allocate one more ptrtab entry than we need, for the initial zero,
! 41: plus one because the caller will probably allocate a new type. */
! 42:
! 43: if (fp->ctf_ptrtab == NULL)
! 44: new_ptrtab_len = 1024;
! 45: else if ((fp->ctf_typemax + 2) > fp->ctf_ptrtab_len)
! 46: new_ptrtab_len = fp->ctf_ptrtab_len * 1.25;
! 47:
! 48: if (new_ptrtab_len != fp->ctf_ptrtab_len)
! 49: {
! 50: uint32_t *new_ptrtab;
! 51:
! 52: if ((new_ptrtab = realloc (fp->ctf_ptrtab,
! 53: new_ptrtab_len * sizeof (uint32_t))) == NULL)
! 54: return (ctf_set_errno (fp, ENOMEM));
! 55:
! 56: fp->ctf_ptrtab = new_ptrtab;
! 57: memset (fp->ctf_ptrtab + fp->ctf_ptrtab_len, 0,
! 58: (new_ptrtab_len - fp->ctf_ptrtab_len) * sizeof (uint32_t));
! 59: fp->ctf_ptrtab_len = new_ptrtab_len;
! 60: }
! 61: return 0;
! 62: }
! 63:
! 64: /* To create an empty CTF container, we just declare a zeroed header and call
! 65: ctf_bufopen() on it. If ctf_bufopen succeeds, we mark the new container r/w
! 66: and initialize the dynamic members. We start assigning type IDs at 1 because
! 67: type ID 0 is used as a sentinel and a not-found indicator. */
! 68:
! 69: ctf_file_t *
! 70: ctf_create (int *errp)
! 71: {
! 72: static const ctf_header_t hdr = { .cth_preamble = { CTF_MAGIC, CTF_VERSION, 0 } };
! 73:
! 74: ctf_dynhash_t *dthash;
! 75: ctf_dynhash_t *dvhash;
! 76: ctf_dynhash_t *structs = NULL, *unions = NULL, *enums = NULL, *names = NULL;
! 77: ctf_sect_t cts;
! 78: ctf_file_t *fp;
! 79:
! 80: libctf_init_debug();
! 81: dthash = ctf_dynhash_create (ctf_hash_integer, ctf_hash_eq_integer,
! 82: NULL, NULL);
! 83: if (dthash == NULL)
! 84: {
! 85: ctf_set_open_errno (errp, EAGAIN);
! 86: goto err;
! 87: }
! 88:
! 89: dvhash = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
! 90: NULL, NULL);
! 91: if (dvhash == NULL)
! 92: {
! 93: ctf_set_open_errno (errp, EAGAIN);
! 94: goto err_dt;
! 95: }
! 96:
! 97: structs = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
! 98: NULL, NULL);
! 99: unions = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
! 100: NULL, NULL);
! 101: enums = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
! 102: NULL, NULL);
! 103: names = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
! 104: NULL, NULL);
! 105: if (!structs || !unions || !enums || !names)
! 106: {
! 107: ctf_set_open_errno (errp, EAGAIN);
! 108: goto err_dv;
! 109: }
! 110:
! 111: cts.cts_name = _CTF_SECTION;
! 112: cts.cts_data = &hdr;
! 113: cts.cts_size = sizeof (hdr);
! 114: cts.cts_entsize = 1;
! 115:
! 116: if ((fp = ctf_bufopen_internal (&cts, NULL, NULL, NULL, 1, errp)) == NULL)
! 117: goto err_dv;
! 118:
! 119: fp->ctf_structs.ctn_writable = structs;
! 120: fp->ctf_unions.ctn_writable = unions;
! 121: fp->ctf_enums.ctn_writable = enums;
! 122: fp->ctf_names.ctn_writable = names;
! 123: fp->ctf_dthash = dthash;
! 124: fp->ctf_dvhash = dvhash;
! 125: fp->ctf_dtoldid = 0;
! 126: fp->ctf_snapshots = 1;
! 127: fp->ctf_snapshot_lu = 0;
! 128:
! 129: ctf_set_ctl_hashes (fp);
! 130: ctf_setmodel (fp, CTF_MODEL_NATIVE);
! 131: if (ctf_grow_ptrtab (fp) < 0)
! 132: {
! 133: ctf_set_open_errno (errp, ctf_errno (fp));
! 134: ctf_file_close (fp);
! 135: return NULL;
! 136: }
! 137:
! 138: return fp;
! 139:
! 140: err_dv:
! 141: ctf_dynhash_destroy (structs);
! 142: ctf_dynhash_destroy (unions);
! 143: ctf_dynhash_destroy (enums);
! 144: ctf_dynhash_destroy (names);
! 145: ctf_dynhash_destroy (dvhash);
! 146: err_dt:
! 147: ctf_dynhash_destroy (dthash);
! 148: err:
! 149: return NULL;
! 150: }
! 151:
! 152: static unsigned char *
! 153: ctf_copy_smembers (ctf_file_t *fp, ctf_dtdef_t *dtd, unsigned char *t)
! 154: {
! 155: ctf_dmdef_t *dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
! 156: ctf_member_t ctm;
! 157:
! 158: for (; dmd != NULL; dmd = ctf_list_next (dmd))
! 159: {
! 160: ctf_member_t *copied;
! 161:
! 162: ctm.ctm_name = 0;
! 163: ctm.ctm_type = (uint32_t) dmd->dmd_type;
! 164: ctm.ctm_offset = (uint32_t) dmd->dmd_offset;
! 165:
! 166: memcpy (t, &ctm, sizeof (ctm));
! 167: copied = (ctf_member_t *) t;
! 168: if (dmd->dmd_name)
! 169: ctf_str_add_ref (fp, dmd->dmd_name, &copied->ctm_name);
! 170:
! 171: t += sizeof (ctm);
! 172: }
! 173:
! 174: return t;
! 175: }
! 176:
! 177: static unsigned char *
! 178: ctf_copy_lmembers (ctf_file_t *fp, ctf_dtdef_t *dtd, unsigned char *t)
! 179: {
! 180: ctf_dmdef_t *dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
! 181: ctf_lmember_t ctlm;
! 182:
! 183: for (; dmd != NULL; dmd = ctf_list_next (dmd))
! 184: {
! 185: ctf_lmember_t *copied;
! 186:
! 187: ctlm.ctlm_name = 0;
! 188: ctlm.ctlm_type = (uint32_t) dmd->dmd_type;
! 189: ctlm.ctlm_offsethi = CTF_OFFSET_TO_LMEMHI (dmd->dmd_offset);
! 190: ctlm.ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO (dmd->dmd_offset);
! 191:
! 192: memcpy (t, &ctlm, sizeof (ctlm));
! 193: copied = (ctf_lmember_t *) t;
! 194: if (dmd->dmd_name)
! 195: ctf_str_add_ref (fp, dmd->dmd_name, &copied->ctlm_name);
! 196:
! 197: t += sizeof (ctlm);
! 198: }
! 199:
! 200: return t;
! 201: }
! 202:
! 203: static unsigned char *
! 204: ctf_copy_emembers (ctf_file_t *fp, ctf_dtdef_t *dtd, unsigned char *t)
! 205: {
! 206: ctf_dmdef_t *dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
! 207: ctf_enum_t cte;
! 208:
! 209: for (; dmd != NULL; dmd = ctf_list_next (dmd))
! 210: {
! 211: ctf_enum_t *copied;
! 212:
! 213: cte.cte_value = dmd->dmd_value;
! 214: memcpy (t, &cte, sizeof (cte));
! 215: copied = (ctf_enum_t *) t;
! 216: ctf_str_add_ref (fp, dmd->dmd_name, &copied->cte_name);
! 217: t += sizeof (cte);
! 218: }
! 219:
! 220: return t;
! 221: }
! 222:
! 223: /* Sort a newly-constructed static variable array. */
! 224:
! 225: typedef struct ctf_sort_var_arg_cb
! 226: {
! 227: ctf_file_t *fp;
! 228: ctf_strs_t *strtab;
! 229: } ctf_sort_var_arg_cb_t;
! 230:
! 231: static int
! 232: ctf_sort_var (const void *one_, const void *two_, void *arg_)
! 233: {
! 234: const ctf_varent_t *one = one_;
! 235: const ctf_varent_t *two = two_;
! 236: ctf_sort_var_arg_cb_t *arg = arg_;
! 237:
! 238: return (strcmp (ctf_strraw_explicit (arg->fp, one->ctv_name, arg->strtab),
! 239: ctf_strraw_explicit (arg->fp, two->ctv_name, arg->strtab)));
! 240: }
! 241:
! 242: /* Compatibility: just update the threshold for ctf_discard. */
! 243: int
! 244: ctf_update (ctf_file_t *fp)
! 245: {
! 246: if (!(fp->ctf_flags & LCTF_RDWR))
! 247: return (ctf_set_errno (fp, ECTF_RDONLY));
! 248:
! 249: fp->ctf_dtoldid = fp->ctf_typemax;
! 250: return 0;
! 251: }
! 252:
! 253: /* If the specified CTF container is writable and has been modified, reload this
! 254: container with the updated type definitions, ready for serialization. In
! 255: order to make this code and the rest of libctf as simple as possible, we
! 256: perform updates by taking the dynamic type definitions and creating an
! 257: in-memory CTF file containing the definitions, and then call
! 258: ctf_simple_open_internal() on it. We perform one extra trick here for the
! 259: benefit of callers and to keep our code simple: ctf_simple_open_internal()
! 260: will return a new ctf_file_t, but we want to keep the fp constant for the
! 261: caller, so after ctf_simple_open_internal() returns, we use memcpy to swap
! 262: the interior of the old and new ctf_file_t's, and then free the old. */
! 263: int
! 264: ctf_serialize (ctf_file_t *fp)
! 265: {
! 266: ctf_file_t ofp, *nfp;
! 267: ctf_header_t hdr, *hdrp;
! 268: ctf_dtdef_t *dtd;
! 269: ctf_dvdef_t *dvd;
! 270: ctf_varent_t *dvarents;
! 271: ctf_strs_writable_t strtab;
! 272:
! 273: unsigned char *t;
! 274: unsigned long i;
! 275: size_t buf_size, type_size, nvars;
! 276: unsigned char *buf, *newbuf;
! 277: int err;
! 278:
! 279: if (!(fp->ctf_flags & LCTF_RDWR))
! 280: return (ctf_set_errno (fp, ECTF_RDONLY));
! 281:
! 282: /* Update required? */
! 283: if (!(fp->ctf_flags & LCTF_DIRTY))
! 284: return 0;
! 285:
! 286: /* Fill in an initial CTF header. We will leave the label, object,
! 287: and function sections empty and only output a header, type section,
! 288: and string table. The type section begins at a 4-byte aligned
! 289: boundary past the CTF header itself (at relative offset zero). */
! 290:
! 291: memset (&hdr, 0, sizeof (hdr));
! 292: hdr.cth_magic = CTF_MAGIC;
! 293: hdr.cth_version = CTF_VERSION;
! 294:
! 295: /* Iterate through the dynamic type definition list and compute the
! 296: size of the CTF type section we will need to generate. */
! 297:
! 298: for (type_size = 0, dtd = ctf_list_next (&fp->ctf_dtdefs);
! 299: dtd != NULL; dtd = ctf_list_next (dtd))
! 300: {
! 301: uint32_t kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
! 302: uint32_t vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
! 303:
! 304: if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)
! 305: type_size += sizeof (ctf_stype_t);
! 306: else
! 307: type_size += sizeof (ctf_type_t);
! 308:
! 309: switch (kind)
! 310: {
! 311: case CTF_K_INTEGER:
! 312: case CTF_K_FLOAT:
! 313: type_size += sizeof (uint32_t);
! 314: break;
! 315: case CTF_K_ARRAY:
! 316: type_size += sizeof (ctf_array_t);
! 317: break;
! 318: case CTF_K_SLICE:
! 319: type_size += sizeof (ctf_slice_t);
! 320: break;
! 321: case CTF_K_FUNCTION:
! 322: type_size += sizeof (uint32_t) * (vlen + (vlen & 1));
! 323: break;
! 324: case CTF_K_STRUCT:
! 325: case CTF_K_UNION:
! 326: if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH)
! 327: type_size += sizeof (ctf_member_t) * vlen;
! 328: else
! 329: type_size += sizeof (ctf_lmember_t) * vlen;
! 330: break;
! 331: case CTF_K_ENUM:
! 332: type_size += sizeof (ctf_enum_t) * vlen;
! 333: break;
! 334: }
! 335: }
! 336:
! 337: /* Computing the number of entries in the CTF variable section is much
! 338: simpler. */
! 339:
! 340: for (nvars = 0, dvd = ctf_list_next (&fp->ctf_dvdefs);
! 341: dvd != NULL; dvd = ctf_list_next (dvd), nvars++);
! 342:
! 343: /* Compute the size of the CTF buffer we need, sans only the string table,
! 344: then allocate a new buffer and memcpy the finished header to the start of
! 345: the buffer. (We will adjust this later with strtab length info.) */
! 346:
! 347: hdr.cth_typeoff = hdr.cth_varoff + (nvars * sizeof (ctf_varent_t));
! 348: hdr.cth_stroff = hdr.cth_typeoff + type_size;
! 349: hdr.cth_strlen = 0;
! 350:
! 351: buf_size = sizeof (ctf_header_t) + hdr.cth_stroff + hdr.cth_strlen;
! 352:
! 353: if ((buf = malloc (buf_size)) == NULL)
! 354: return (ctf_set_errno (fp, EAGAIN));
! 355:
! 356: memcpy (buf, &hdr, sizeof (ctf_header_t));
! 357: t = (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_varoff;
! 358:
! 359: hdrp = (ctf_header_t *) buf;
! 360: if ((fp->ctf_flags & LCTF_CHILD) && (fp->ctf_parname != NULL))
! 361: ctf_str_add_ref (fp, fp->ctf_parname, &hdrp->cth_parname);
! 362: if (fp->ctf_cuname != NULL)
! 363: ctf_str_add_ref (fp, fp->ctf_cuname, &hdrp->cth_cuname);
! 364:
! 365: /* Work over the variable list, translating everything into ctf_varent_t's and
! 366: prepping the string table. */
! 367:
! 368: dvarents = (ctf_varent_t *) t;
! 369: for (i = 0, dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL;
! 370: dvd = ctf_list_next (dvd), i++)
! 371: {
! 372: ctf_varent_t *var = &dvarents[i];
! 373:
! 374: ctf_str_add_ref (fp, dvd->dvd_name, &var->ctv_name);
! 375: var->ctv_type = dvd->dvd_type;
! 376: }
! 377: assert (i == nvars);
! 378:
! 379: t += sizeof (ctf_varent_t) * nvars;
! 380:
! 381: assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_typeoff);
! 382:
! 383: /* We now take a final lap through the dynamic type definition list and copy
! 384: the appropriate type records to the output buffer, noting down the
! 385: strings as we go. */
! 386:
! 387: for (dtd = ctf_list_next (&fp->ctf_dtdefs);
! 388: dtd != NULL; dtd = ctf_list_next (dtd))
! 389: {
! 390: uint32_t kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
! 391: uint32_t vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
! 392:
! 393: ctf_array_t cta;
! 394: uint32_t encoding;
! 395: size_t len;
! 396: ctf_stype_t *copied;
! 397: const char *name;
! 398:
! 399: if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)
! 400: len = sizeof (ctf_stype_t);
! 401: else
! 402: len = sizeof (ctf_type_t);
! 403:
! 404: memcpy (t, &dtd->dtd_data, len);
! 405: copied = (ctf_stype_t *) t; /* name is at the start: constant offset. */
! 406: if (copied->ctt_name
! 407: && (name = ctf_strraw (fp, copied->ctt_name)) != NULL)
! 408: ctf_str_add_ref (fp, name, &copied->ctt_name);
! 409: t += len;
! 410:
! 411: switch (kind)
! 412: {
! 413: case CTF_K_INTEGER:
! 414: case CTF_K_FLOAT:
! 415: if (kind == CTF_K_INTEGER)
! 416: {
! 417: encoding = CTF_INT_DATA (dtd->dtd_u.dtu_enc.cte_format,
! 418: dtd->dtd_u.dtu_enc.cte_offset,
! 419: dtd->dtd_u.dtu_enc.cte_bits);
! 420: }
! 421: else
! 422: {
! 423: encoding = CTF_FP_DATA (dtd->dtd_u.dtu_enc.cte_format,
! 424: dtd->dtd_u.dtu_enc.cte_offset,
! 425: dtd->dtd_u.dtu_enc.cte_bits);
! 426: }
! 427: memcpy (t, &encoding, sizeof (encoding));
! 428: t += sizeof (encoding);
! 429: break;
! 430:
! 431: case CTF_K_SLICE:
! 432: memcpy (t, &dtd->dtd_u.dtu_slice, sizeof (struct ctf_slice));
! 433: t += sizeof (struct ctf_slice);
! 434: break;
! 435:
! 436: case CTF_K_ARRAY:
! 437: cta.cta_contents = (uint32_t) dtd->dtd_u.dtu_arr.ctr_contents;
! 438: cta.cta_index = (uint32_t) dtd->dtd_u.dtu_arr.ctr_index;
! 439: cta.cta_nelems = dtd->dtd_u.dtu_arr.ctr_nelems;
! 440: memcpy (t, &cta, sizeof (cta));
! 441: t += sizeof (cta);
! 442: break;
! 443:
! 444: case CTF_K_FUNCTION:
! 445: {
! 446: uint32_t *argv = (uint32_t *) (uintptr_t) t;
! 447: uint32_t argc;
! 448:
! 449: for (argc = 0; argc < vlen; argc++)
! 450: *argv++ = (uint32_t) dtd->dtd_u.dtu_argv[argc];
! 451:
! 452: if (vlen & 1)
! 453: *argv++ = 0; /* Pad to 4-byte boundary. */
! 454:
! 455: t = (unsigned char *) argv;
! 456: break;
! 457: }
! 458:
! 459: case CTF_K_STRUCT:
! 460: case CTF_K_UNION:
! 461: if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH)
! 462: t = ctf_copy_smembers (fp, dtd, t);
! 463: else
! 464: t = ctf_copy_lmembers (fp, dtd, t);
! 465: break;
! 466:
! 467: case CTF_K_ENUM:
! 468: t = ctf_copy_emembers (fp, dtd, t);
! 469: break;
! 470: }
! 471: }
! 472: assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_stroff);
! 473:
! 474: /* Construct the final string table and fill out all the string refs with the
! 475: final offsets. Then purge the refs list, because we're about to move this
! 476: strtab onto the end of the buf, invalidating all the offsets. */
! 477: strtab = ctf_str_write_strtab (fp);
! 478: ctf_str_purge_refs (fp);
! 479:
! 480: if (strtab.cts_strs == NULL)
! 481: {
! 482: free (buf);
! 483: return (ctf_set_errno (fp, EAGAIN));
! 484: }
! 485:
! 486: /* Now the string table is constructed, we can sort the buffer of
! 487: ctf_varent_t's. */
! 488: ctf_sort_var_arg_cb_t sort_var_arg = { fp, (ctf_strs_t *) &strtab };
! 489: ctf_qsort_r (dvarents, nvars, sizeof (ctf_varent_t), ctf_sort_var,
! 490: &sort_var_arg);
! 491:
! 492: if ((newbuf = ctf_realloc (fp, buf, buf_size + strtab.cts_len)) == NULL)
! 493: {
! 494: free (buf);
! 495: free (strtab.cts_strs);
! 496: return (ctf_set_errno (fp, EAGAIN));
! 497: }
! 498: buf = newbuf;
! 499: memcpy (buf + buf_size, strtab.cts_strs, strtab.cts_len);
! 500: hdrp = (ctf_header_t *) buf;
! 501: hdrp->cth_strlen = strtab.cts_len;
! 502: buf_size += hdrp->cth_strlen;
! 503: free (strtab.cts_strs);
! 504:
! 505: /* Finally, we are ready to ctf_simple_open() the new container. If this
! 506: is successful, we then switch nfp and fp and free the old container. */
! 507:
! 508: if ((nfp = ctf_simple_open_internal ((char *) buf, buf_size, NULL, 0,
! 509: 0, NULL, 0, fp->ctf_syn_ext_strtab,
! 510: 1, &err)) == NULL)
! 511: {
! 512: free (buf);
! 513: return (ctf_set_errno (fp, err));
! 514: }
! 515:
! 516: (void) ctf_setmodel (nfp, ctf_getmodel (fp));
! 517: (void) ctf_import (nfp, fp->ctf_parent);
! 518:
! 519: nfp->ctf_refcnt = fp->ctf_refcnt;
! 520: nfp->ctf_flags |= fp->ctf_flags & ~LCTF_DIRTY;
! 521: if (nfp->ctf_dynbase == NULL)
! 522: nfp->ctf_dynbase = buf; /* Make sure buf is freed on close. */
! 523: nfp->ctf_dthash = fp->ctf_dthash;
! 524: nfp->ctf_dtdefs = fp->ctf_dtdefs;
! 525: nfp->ctf_dvhash = fp->ctf_dvhash;
! 526: nfp->ctf_dvdefs = fp->ctf_dvdefs;
! 527: nfp->ctf_dtoldid = fp->ctf_dtoldid;
! 528: nfp->ctf_add_processing = fp->ctf_add_processing;
! 529: nfp->ctf_snapshots = fp->ctf_snapshots + 1;
! 530: nfp->ctf_specific = fp->ctf_specific;
! 531: nfp->ctf_ptrtab = fp->ctf_ptrtab;
! 532: nfp->ctf_ptrtab_len = fp->ctf_ptrtab_len;
! 533: nfp->ctf_link_inputs = fp->ctf_link_inputs;
! 534: nfp->ctf_link_outputs = fp->ctf_link_outputs;
! 535: nfp->ctf_str_prov_offset = fp->ctf_str_prov_offset;
! 536: nfp->ctf_syn_ext_strtab = fp->ctf_syn_ext_strtab;
! 537: nfp->ctf_link_cu_mapping = fp->ctf_link_cu_mapping;
! 538: nfp->ctf_link_type_mapping = fp->ctf_link_type_mapping;
! 539: nfp->ctf_link_memb_name_changer = fp->ctf_link_memb_name_changer;
! 540: nfp->ctf_link_memb_name_changer_arg = fp->ctf_link_memb_name_changer_arg;
! 541:
! 542: nfp->ctf_snapshot_lu = fp->ctf_snapshots;
! 543:
! 544: memcpy (&nfp->ctf_lookups, fp->ctf_lookups, sizeof (fp->ctf_lookups));
! 545: nfp->ctf_structs = fp->ctf_structs;
! 546: nfp->ctf_unions = fp->ctf_unions;
! 547: nfp->ctf_enums = fp->ctf_enums;
! 548: nfp->ctf_names = fp->ctf_names;
! 549:
! 550: fp->ctf_dthash = NULL;
! 551: ctf_str_free_atoms (nfp);
! 552: nfp->ctf_str_atoms = fp->ctf_str_atoms;
! 553: nfp->ctf_prov_strtab = fp->ctf_prov_strtab;
! 554: fp->ctf_str_atoms = NULL;
! 555: fp->ctf_prov_strtab = NULL;
! 556: memset (&fp->ctf_dtdefs, 0, sizeof (ctf_list_t));
! 557: fp->ctf_add_processing = NULL;
! 558: fp->ctf_ptrtab = NULL;
! 559: fp->ctf_link_inputs = NULL;
! 560: fp->ctf_link_outputs = NULL;
! 561: fp->ctf_syn_ext_strtab = NULL;
! 562: fp->ctf_link_cu_mapping = NULL;
! 563: fp->ctf_link_type_mapping = NULL;
! 564:
! 565: fp->ctf_dvhash = NULL;
! 566: memset (&fp->ctf_dvdefs, 0, sizeof (ctf_list_t));
! 567: memset (fp->ctf_lookups, 0, sizeof (fp->ctf_lookups));
! 568: fp->ctf_structs.ctn_writable = NULL;
! 569: fp->ctf_unions.ctn_writable = NULL;
! 570: fp->ctf_enums.ctn_writable = NULL;
! 571: fp->ctf_names.ctn_writable = NULL;
! 572:
! 573: memcpy (&ofp, fp, sizeof (ctf_file_t));
! 574: memcpy (fp, nfp, sizeof (ctf_file_t));
! 575: memcpy (nfp, &ofp, sizeof (ctf_file_t));
! 576:
! 577: nfp->ctf_refcnt = 1; /* Force nfp to be freed. */
! 578: ctf_file_close (nfp);
! 579:
! 580: return 0;
! 581: }
! 582:
! 583: ctf_names_t *
! 584: ctf_name_table (ctf_file_t *fp, int kind)
! 585: {
! 586: switch (kind)
! 587: {
! 588: case CTF_K_STRUCT:
! 589: return &fp->ctf_structs;
! 590: case CTF_K_UNION:
! 591: return &fp->ctf_unions;
! 592: case CTF_K_ENUM:
! 593: return &fp->ctf_enums;
! 594: default:
! 595: return &fp->ctf_names;
! 596: }
! 597: }
! 598:
! 599: int
! 600: ctf_dtd_insert (ctf_file_t *fp, ctf_dtdef_t *dtd, int kind)
! 601: {
! 602: const char *name;
! 603: if (ctf_dynhash_insert (fp->ctf_dthash, (void *) dtd->dtd_type, dtd) < 0)
! 604: return -1;
! 605:
! 606: if (dtd->dtd_data.ctt_name
! 607: && (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL)
! 608: {
! 609: if (ctf_dynhash_insert (ctf_name_table (fp, kind)->ctn_writable,
! 610: (char *) name, (void *) dtd->dtd_type) < 0)
! 611: {
! 612: ctf_dynhash_remove (fp->ctf_dthash, (void *) dtd->dtd_type);
! 613: return -1;
! 614: }
! 615: }
! 616: ctf_list_append (&fp->ctf_dtdefs, dtd);
! 617: return 0;
! 618: }
! 619:
! 620: void
! 621: ctf_dtd_delete (ctf_file_t *fp, ctf_dtdef_t *dtd)
! 622: {
! 623: ctf_dmdef_t *dmd, *nmd;
! 624: int kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
! 625: const char *name;
! 626:
! 627: ctf_dynhash_remove (fp->ctf_dthash, (void *) dtd->dtd_type);
! 628:
! 629: switch (kind)
! 630: {
! 631: case CTF_K_STRUCT:
! 632: case CTF_K_UNION:
! 633: case CTF_K_ENUM:
! 634: for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
! 635: dmd != NULL; dmd = nmd)
! 636: {
! 637: if (dmd->dmd_name != NULL)
! 638: free (dmd->dmd_name);
! 639: nmd = ctf_list_next (dmd);
! 640: free (dmd);
! 641: }
! 642: break;
! 643: case CTF_K_FUNCTION:
! 644: free (dtd->dtd_u.dtu_argv);
! 645: break;
! 646: }
! 647:
! 648: if (dtd->dtd_data.ctt_name
! 649: && (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL)
! 650: {
! 651: ctf_dynhash_remove (ctf_name_table (fp, kind)->ctn_writable,
! 652: name);
! 653: ctf_str_remove_ref (fp, name, &dtd->dtd_data.ctt_name);
! 654: }
! 655:
! 656: ctf_list_delete (&fp->ctf_dtdefs, dtd);
! 657: free (dtd);
! 658: }
! 659:
! 660: ctf_dtdef_t *
! 661: ctf_dtd_lookup (const ctf_file_t *fp, ctf_id_t type)
! 662: {
! 663: return (ctf_dtdef_t *) ctf_dynhash_lookup (fp->ctf_dthash, (void *) type);
! 664: }
! 665:
! 666: ctf_dtdef_t *
! 667: ctf_dynamic_type (const ctf_file_t *fp, ctf_id_t id)
! 668: {
! 669: ctf_id_t idx;
! 670:
! 671: if (!(fp->ctf_flags & LCTF_RDWR))
! 672: return NULL;
! 673:
! 674: if ((fp->ctf_flags & LCTF_CHILD) && LCTF_TYPE_ISPARENT (fp, id))
! 675: fp = fp->ctf_parent;
! 676:
! 677: idx = LCTF_TYPE_TO_INDEX(fp, id);
! 678:
! 679: if ((unsigned long) idx <= fp->ctf_typemax)
! 680: return ctf_dtd_lookup (fp, id);
! 681: return NULL;
! 682: }
! 683:
! 684: int
! 685: ctf_dvd_insert (ctf_file_t *fp, ctf_dvdef_t *dvd)
! 686: {
! 687: if (ctf_dynhash_insert (fp->ctf_dvhash, dvd->dvd_name, dvd) < 0)
! 688: return -1;
! 689: ctf_list_append (&fp->ctf_dvdefs, dvd);
! 690: return 0;
! 691: }
! 692:
! 693: void
! 694: ctf_dvd_delete (ctf_file_t *fp, ctf_dvdef_t *dvd)
! 695: {
! 696: ctf_dynhash_remove (fp->ctf_dvhash, dvd->dvd_name);
! 697: free (dvd->dvd_name);
! 698:
! 699: ctf_list_delete (&fp->ctf_dvdefs, dvd);
! 700: free (dvd);
! 701: }
! 702:
! 703: ctf_dvdef_t *
! 704: ctf_dvd_lookup (const ctf_file_t *fp, const char *name)
! 705: {
! 706: return (ctf_dvdef_t *) ctf_dynhash_lookup (fp->ctf_dvhash, name);
! 707: }
! 708:
! 709: /* Discard all of the dynamic type definitions and variable definitions that
! 710: have been added to the container since the last call to ctf_update(). We
! 711: locate such types by scanning the dtd list and deleting elements that have
! 712: type IDs greater than ctf_dtoldid, which is set by ctf_update(), above, and
! 713: by scanning the variable list and deleting elements that have update IDs
! 714: equal to the current value of the last-update snapshot count (indicating that
! 715: they were added after the most recent call to ctf_update()). */
! 716: int
! 717: ctf_discard (ctf_file_t *fp)
! 718: {
! 719: ctf_snapshot_id_t last_update =
! 720: { fp->ctf_dtoldid,
! 721: fp->ctf_snapshot_lu + 1 };
! 722:
! 723: /* Update required? */
! 724: if (!(fp->ctf_flags & LCTF_DIRTY))
! 725: return 0;
! 726:
! 727: return (ctf_rollback (fp, last_update));
! 728: }
! 729:
! 730: ctf_snapshot_id_t
! 731: ctf_snapshot (ctf_file_t *fp)
! 732: {
! 733: ctf_snapshot_id_t snapid;
! 734: snapid.dtd_id = fp->ctf_typemax;
! 735: snapid.snapshot_id = fp->ctf_snapshots++;
! 736: return snapid;
! 737: }
! 738:
! 739: /* Like ctf_discard(), only discards everything after a particular ID. */
! 740: int
! 741: ctf_rollback (ctf_file_t *fp, ctf_snapshot_id_t id)
! 742: {
! 743: ctf_dtdef_t *dtd, *ntd;
! 744: ctf_dvdef_t *dvd, *nvd;
! 745:
! 746: if (!(fp->ctf_flags & LCTF_RDWR))
! 747: return (ctf_set_errno (fp, ECTF_RDONLY));
! 748:
! 749: if (fp->ctf_snapshot_lu >= id.snapshot_id)
! 750: return (ctf_set_errno (fp, ECTF_OVERROLLBACK));
! 751:
! 752: for (dtd = ctf_list_next (&fp->ctf_dtdefs); dtd != NULL; dtd = ntd)
! 753: {
! 754: int kind;
! 755: const char *name;
! 756:
! 757: ntd = ctf_list_next (dtd);
! 758:
! 759: if (LCTF_TYPE_TO_INDEX (fp, dtd->dtd_type) <= id.dtd_id)
! 760: continue;
! 761:
! 762: kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
! 763:
! 764: if (dtd->dtd_data.ctt_name
! 765: && (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL)
! 766: {
! 767: ctf_dynhash_remove (ctf_name_table (fp, kind)->ctn_writable,
! 768: name);
! 769: ctf_str_remove_ref (fp, name, &dtd->dtd_data.ctt_name);
! 770: }
! 771:
! 772: ctf_dynhash_remove (fp->ctf_dthash, (void *) dtd->dtd_type);
! 773: ctf_dtd_delete (fp, dtd);
! 774: }
! 775:
! 776: for (dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; dvd = nvd)
! 777: {
! 778: nvd = ctf_list_next (dvd);
! 779:
! 780: if (dvd->dvd_snapshots <= id.snapshot_id)
! 781: continue;
! 782:
! 783: ctf_dvd_delete (fp, dvd);
! 784: }
! 785:
! 786: fp->ctf_typemax = id.dtd_id;
! 787: fp->ctf_snapshots = id.snapshot_id;
! 788:
! 789: if (fp->ctf_snapshots == fp->ctf_snapshot_lu)
! 790: fp->ctf_flags &= ~LCTF_DIRTY;
! 791:
! 792: return 0;
! 793: }
! 794:
! 795: static ctf_id_t
! 796: ctf_add_generic (ctf_file_t *fp, uint32_t flag, const char *name, int kind,
! 797: ctf_dtdef_t **rp)
! 798: {
! 799: ctf_dtdef_t *dtd;
! 800: ctf_id_t type;
! 801:
! 802: if (flag != CTF_ADD_NONROOT && flag != CTF_ADD_ROOT)
! 803: return (ctf_set_errno (fp, EINVAL));
! 804:
! 805: if (!(fp->ctf_flags & LCTF_RDWR))
! 806: return (ctf_set_errno (fp, ECTF_RDONLY));
! 807:
! 808: if (LCTF_INDEX_TO_TYPE (fp, fp->ctf_typemax, 1) >= CTF_MAX_TYPE)
! 809: return (ctf_set_errno (fp, ECTF_FULL));
! 810:
! 811: if (LCTF_INDEX_TO_TYPE (fp, fp->ctf_typemax, 1) == (CTF_MAX_PTYPE - 1))
! 812: return (ctf_set_errno (fp, ECTF_FULL));
! 813:
! 814: /* Make sure ptrtab always grows to be big enough for all types. */
! 815: if (ctf_grow_ptrtab (fp) < 0)
! 816: return CTF_ERR; /* errno is set for us. */
! 817:
! 818: if ((dtd = malloc (sizeof (ctf_dtdef_t))) == NULL)
! 819: return (ctf_set_errno (fp, EAGAIN));
! 820:
! 821: type = ++fp->ctf_typemax;
! 822: type = LCTF_INDEX_TO_TYPE (fp, type, (fp->ctf_flags & LCTF_CHILD));
! 823:
! 824: memset (dtd, 0, sizeof (ctf_dtdef_t));
! 825: dtd->dtd_data.ctt_name = ctf_str_add_ref (fp, name, &dtd->dtd_data.ctt_name);
! 826: dtd->dtd_type = type;
! 827:
! 828: if (dtd->dtd_data.ctt_name == 0 && name != NULL && name[0] != '\0')
! 829: {
! 830: free (dtd);
! 831: return (ctf_set_errno (fp, EAGAIN));
! 832: }
! 833:
! 834: if (ctf_dtd_insert (fp, dtd, kind) < 0)
! 835: {
! 836: free (dtd);
! 837: return CTF_ERR; /* errno is set for us. */
! 838: }
! 839: fp->ctf_flags |= LCTF_DIRTY;
! 840:
! 841: *rp = dtd;
! 842: return type;
! 843: }
! 844:
! 845: /* When encoding integer sizes, we want to convert a byte count in the range
! 846: 1-8 to the closest power of 2 (e.g. 3->4, 5->8, etc). The clp2() function
! 847: is a clever implementation from "Hacker's Delight" by Henry Warren, Jr. */
! 848: static size_t
! 849: clp2 (size_t x)
! 850: {
! 851: x--;
! 852:
! 853: x |= (x >> 1);
! 854: x |= (x >> 2);
! 855: x |= (x >> 4);
! 856: x |= (x >> 8);
! 857: x |= (x >> 16);
! 858:
! 859: return (x + 1);
! 860: }
! 861:
! 862: static ctf_id_t
! 863: ctf_add_encoded (ctf_file_t *fp, uint32_t flag,
! 864: const char *name, const ctf_encoding_t *ep, uint32_t kind)
! 865: {
! 866: ctf_dtdef_t *dtd;
! 867: ctf_id_t type;
! 868:
! 869: if (ep == NULL)
! 870: return (ctf_set_errno (fp, EINVAL));
! 871:
! 872: if ((type = ctf_add_generic (fp, flag, name, kind, &dtd)) == CTF_ERR)
! 873: return CTF_ERR; /* errno is set for us. */
! 874:
! 875: dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, flag, 0);
! 876: dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, CHAR_BIT)
! 877: / CHAR_BIT);
! 878: dtd->dtd_u.dtu_enc = *ep;
! 879:
! 880: return type;
! 881: }
! 882:
! 883: static ctf_id_t
! 884: ctf_add_reftype (ctf_file_t *fp, uint32_t flag, ctf_id_t ref, uint32_t kind)
! 885: {
! 886: ctf_dtdef_t *dtd;
! 887: ctf_id_t type;
! 888: ctf_file_t *tmp = fp;
! 889: int child = fp->ctf_flags & LCTF_CHILD;
! 890:
! 891: if (ref == CTF_ERR || ref > CTF_MAX_TYPE)
! 892: return (ctf_set_errno (fp, EINVAL));
! 893:
! 894: if (ctf_lookup_by_id (&tmp, ref) == NULL)
! 895: return CTF_ERR; /* errno is set for us. */
! 896:
! 897: if ((type = ctf_add_generic (fp, flag, NULL, kind, &dtd)) == CTF_ERR)
! 898: return CTF_ERR; /* errno is set for us. */
! 899:
! 900: dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, flag, 0);
! 901: dtd->dtd_data.ctt_type = (uint32_t) ref;
! 902:
! 903: if (kind != CTF_K_POINTER)
! 904: return type;
! 905:
! 906: /* If we are adding a pointer, update the ptrtab, both the directly pointed-to
! 907: type and (if an anonymous typedef node is being pointed at) the type that
! 908: points at too. Note that ctf_typemax is at this point one higher than we
! 909: want to check against, because it's just been incremented for the addition
! 910: of this type. */
! 911:
! 912: uint32_t type_idx = LCTF_TYPE_TO_INDEX (fp, type);
! 913: uint32_t ref_idx = LCTF_TYPE_TO_INDEX (fp, ref);
! 914:
! 915: if (LCTF_TYPE_ISCHILD (fp, ref) == child
! 916: && ref_idx < fp->ctf_typemax)
! 917: {
! 918: fp->ctf_ptrtab[ref_idx] = type_idx;
! 919:
! 920: ctf_id_t refref_idx = LCTF_TYPE_TO_INDEX (fp, dtd->dtd_data.ctt_type);
! 921:
! 922: if (tmp == fp
! 923: && (LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info) == CTF_K_TYPEDEF)
! 924: && strcmp (ctf_strptr (fp, dtd->dtd_data.ctt_name), "") == 0
! 925: && refref_idx < fp->ctf_typemax)
! 926: fp->ctf_ptrtab[refref_idx] = type_idx;
! 927: }
! 928:
! 929: return type;
! 930: }
! 931:
! 932: ctf_id_t
! 933: ctf_add_slice (ctf_file_t *fp, uint32_t flag, ctf_id_t ref,
! 934: const ctf_encoding_t *ep)
! 935: {
! 936: ctf_dtdef_t *dtd;
! 937: ctf_id_t type;
! 938: int kind;
! 939: const ctf_type_t *tp;
! 940: ctf_file_t *tmp = fp;
! 941:
! 942: if (ep == NULL)
! 943: return (ctf_set_errno (fp, EINVAL));
! 944:
! 945: if ((ep->cte_bits > 255) || (ep->cte_offset > 255))
! 946: return (ctf_set_errno (fp, ECTF_SLICEOVERFLOW));
! 947:
! 948: if (ref == CTF_ERR || ref > CTF_MAX_TYPE)
! 949: return (ctf_set_errno (fp, EINVAL));
! 950:
! 951: if ((tp = ctf_lookup_by_id (&tmp, ref)) == NULL)
! 952: return CTF_ERR; /* errno is set for us. */
! 953:
! 954: kind = ctf_type_kind_unsliced (tmp, ref);
! 955: if ((kind != CTF_K_INTEGER) && (kind != CTF_K_FLOAT) &&
! 956: (kind != CTF_K_ENUM))
! 957: return (ctf_set_errno (fp, ECTF_NOTINTFP));
! 958:
! 959: if ((type = ctf_add_generic (fp, flag, NULL, CTF_K_SLICE, &dtd)) == CTF_ERR)
! 960: return CTF_ERR; /* errno is set for us. */
! 961:
! 962: dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_SLICE, flag, 0);
! 963: dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, CHAR_BIT)
! 964: / CHAR_BIT);
! 965: dtd->dtd_u.dtu_slice.cts_type = ref;
! 966: dtd->dtd_u.dtu_slice.cts_bits = ep->cte_bits;
! 967: dtd->dtd_u.dtu_slice.cts_offset = ep->cte_offset;
! 968:
! 969: return type;
! 970: }
! 971:
! 972: ctf_id_t
! 973: ctf_add_integer (ctf_file_t *fp, uint32_t flag,
! 974: const char *name, const ctf_encoding_t *ep)
! 975: {
! 976: return (ctf_add_encoded (fp, flag, name, ep, CTF_K_INTEGER));
! 977: }
! 978:
! 979: ctf_id_t
! 980: ctf_add_float (ctf_file_t *fp, uint32_t flag,
! 981: const char *name, const ctf_encoding_t *ep)
! 982: {
! 983: return (ctf_add_encoded (fp, flag, name, ep, CTF_K_FLOAT));
! 984: }
! 985:
! 986: ctf_id_t
! 987: ctf_add_pointer (ctf_file_t *fp, uint32_t flag, ctf_id_t ref)
! 988: {
! 989: return (ctf_add_reftype (fp, flag, ref, CTF_K_POINTER));
! 990: }
! 991:
! 992: ctf_id_t
! 993: ctf_add_array (ctf_file_t *fp, uint32_t flag, const ctf_arinfo_t *arp)
! 994: {
! 995: ctf_dtdef_t *dtd;
! 996: ctf_id_t type;
! 997: ctf_file_t *tmp = fp;
! 998:
! 999: if (arp == NULL)
! 1000: return (ctf_set_errno (fp, EINVAL));
! 1001:
! 1002: if (ctf_lookup_by_id (&tmp, arp->ctr_contents) == NULL)
! 1003: return CTF_ERR; /* errno is set for us. */
! 1004:
! 1005: tmp = fp;
! 1006: if (ctf_lookup_by_id (&tmp, arp->ctr_index) == NULL)
! 1007: return CTF_ERR; /* errno is set for us. */
! 1008:
! 1009: if ((type = ctf_add_generic (fp, flag, NULL, CTF_K_ARRAY, &dtd)) == CTF_ERR)
! 1010: return CTF_ERR; /* errno is set for us. */
! 1011:
! 1012: dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_ARRAY, flag, 0);
! 1013: dtd->dtd_data.ctt_size = 0;
! 1014: dtd->dtd_u.dtu_arr = *arp;
! 1015:
! 1016: return type;
! 1017: }
! 1018:
! 1019: int
! 1020: ctf_set_array (ctf_file_t *fp, ctf_id_t type, const ctf_arinfo_t *arp)
! 1021: {
! 1022: ctf_dtdef_t *dtd = ctf_dtd_lookup (fp, type);
! 1023:
! 1024: if (!(fp->ctf_flags & LCTF_RDWR))
! 1025: return (ctf_set_errno (fp, ECTF_RDONLY));
! 1026:
! 1027: if (dtd == NULL
! 1028: || LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info) != CTF_K_ARRAY)
! 1029: return (ctf_set_errno (fp, ECTF_BADID));
! 1030:
! 1031: fp->ctf_flags |= LCTF_DIRTY;
! 1032: dtd->dtd_u.dtu_arr = *arp;
! 1033:
! 1034: return 0;
! 1035: }
! 1036:
! 1037: ctf_id_t
! 1038: ctf_add_function (ctf_file_t *fp, uint32_t flag,
! 1039: const ctf_funcinfo_t *ctc, const ctf_id_t *argv)
! 1040: {
! 1041: ctf_dtdef_t *dtd;
! 1042: ctf_id_t type;
! 1043: uint32_t vlen;
! 1044: ctf_id_t *vdat = NULL;
! 1045: ctf_file_t *tmp = fp;
! 1046: size_t i;
! 1047:
! 1048: if (ctc == NULL || (ctc->ctc_flags & ~CTF_FUNC_VARARG) != 0
! 1049: || (ctc->ctc_argc != 0 && argv == NULL))
! 1050: return (ctf_set_errno (fp, EINVAL));
! 1051:
! 1052: vlen = ctc->ctc_argc;
! 1053: if (ctc->ctc_flags & CTF_FUNC_VARARG)
! 1054: vlen++; /* Add trailing zero to indicate varargs (see below). */
! 1055:
! 1056: if (ctf_lookup_by_id (&tmp, ctc->ctc_return) == NULL)
! 1057: return CTF_ERR; /* errno is set for us. */
! 1058:
! 1059: for (i = 0; i < ctc->ctc_argc; i++)
! 1060: {
! 1061: tmp = fp;
! 1062: if (ctf_lookup_by_id (&tmp, argv[i]) == NULL)
! 1063: return CTF_ERR; /* errno is set for us. */
! 1064: }
! 1065:
! 1066: if (vlen > CTF_MAX_VLEN)
! 1067: return (ctf_set_errno (fp, EOVERFLOW));
! 1068:
! 1069: if (vlen != 0 && (vdat = malloc (sizeof (ctf_id_t) * vlen)) == NULL)
! 1070: return (ctf_set_errno (fp, EAGAIN));
! 1071:
! 1072: if ((type = ctf_add_generic (fp, flag, NULL, CTF_K_FUNCTION,
! 1073: &dtd)) == CTF_ERR)
! 1074: {
! 1075: free (vdat);
! 1076: return CTF_ERR; /* errno is set for us. */
! 1077: }
! 1078:
! 1079: dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_FUNCTION, flag, vlen);
! 1080: dtd->dtd_data.ctt_type = (uint32_t) ctc->ctc_return;
! 1081:
! 1082: memcpy (vdat, argv, sizeof (ctf_id_t) * ctc->ctc_argc);
! 1083: if (ctc->ctc_flags & CTF_FUNC_VARARG)
! 1084: vdat[vlen - 1] = 0; /* Add trailing zero to indicate varargs. */
! 1085: dtd->dtd_u.dtu_argv = vdat;
! 1086:
! 1087: return type;
! 1088: }
! 1089:
! 1090: ctf_id_t
! 1091: ctf_add_struct_sized (ctf_file_t *fp, uint32_t flag, const char *name,
! 1092: size_t size)
! 1093: {
! 1094: ctf_dtdef_t *dtd;
! 1095: ctf_id_t type = 0;
! 1096:
! 1097: /* Promote forwards to structs. */
! 1098:
! 1099: if (name != NULL)
! 1100: type = ctf_lookup_by_rawname (fp, CTF_K_STRUCT, name);
! 1101:
! 1102: if (type != 0 && ctf_type_kind (fp, type) == CTF_K_FORWARD)
! 1103: dtd = ctf_dtd_lookup (fp, type);
! 1104: else if ((type = ctf_add_generic (fp, flag, name, CTF_K_STRUCT,
! 1105: &dtd)) == CTF_ERR)
! 1106: return CTF_ERR; /* errno is set for us. */
! 1107:
! 1108: dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_STRUCT, flag, 0);
! 1109:
! 1110: if (size > CTF_MAX_SIZE)
! 1111: {
! 1112: dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
! 1113: dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (size);
! 1114: dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (size);
! 1115: }
! 1116: else
! 1117: dtd->dtd_data.ctt_size = (uint32_t) size;
! 1118:
! 1119: return type;
! 1120: }
! 1121:
! 1122: ctf_id_t
! 1123: ctf_add_struct (ctf_file_t *fp, uint32_t flag, const char *name)
! 1124: {
! 1125: return (ctf_add_struct_sized (fp, flag, name, 0));
! 1126: }
! 1127:
! 1128: ctf_id_t
! 1129: ctf_add_union_sized (ctf_file_t *fp, uint32_t flag, const char *name,
! 1130: size_t size)
! 1131: {
! 1132: ctf_dtdef_t *dtd;
! 1133: ctf_id_t type = 0;
! 1134:
! 1135: /* Promote forwards to unions. */
! 1136: if (name != NULL)
! 1137: type = ctf_lookup_by_rawname (fp, CTF_K_UNION, name);
! 1138:
! 1139: if (type != 0 && ctf_type_kind (fp, type) == CTF_K_FORWARD)
! 1140: dtd = ctf_dtd_lookup (fp, type);
! 1141: else if ((type = ctf_add_generic (fp, flag, name, CTF_K_UNION,
! 1142: &dtd)) == CTF_ERR)
! 1143: return CTF_ERR; /* errno is set for us */
! 1144:
! 1145: dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_UNION, flag, 0);
! 1146:
! 1147: if (size > CTF_MAX_SIZE)
! 1148: {
! 1149: dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
! 1150: dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (size);
! 1151: dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (size);
! 1152: }
! 1153: else
! 1154: dtd->dtd_data.ctt_size = (uint32_t) size;
! 1155:
! 1156: return type;
! 1157: }
! 1158:
! 1159: ctf_id_t
! 1160: ctf_add_union (ctf_file_t *fp, uint32_t flag, const char *name)
! 1161: {
! 1162: return (ctf_add_union_sized (fp, flag, name, 0));
! 1163: }
! 1164:
! 1165: ctf_id_t
! 1166: ctf_add_enum (ctf_file_t *fp, uint32_t flag, const char *name)
! 1167: {
! 1168: ctf_dtdef_t *dtd;
! 1169: ctf_id_t type = 0;
! 1170:
! 1171: /* Promote forwards to enums. */
! 1172: if (name != NULL)
! 1173: type = ctf_lookup_by_rawname (fp, CTF_K_ENUM, name);
! 1174:
! 1175: if (type != 0 && ctf_type_kind (fp, type) == CTF_K_FORWARD)
! 1176: dtd = ctf_dtd_lookup (fp, type);
! 1177: else if ((type = ctf_add_generic (fp, flag, name, CTF_K_ENUM,
! 1178: &dtd)) == CTF_ERR)
! 1179: return CTF_ERR; /* errno is set for us. */
! 1180:
! 1181: dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_ENUM, flag, 0);
! 1182: dtd->dtd_data.ctt_size = fp->ctf_dmodel->ctd_int;
! 1183:
! 1184: return type;
! 1185: }
! 1186:
! 1187: ctf_id_t
! 1188: ctf_add_enum_encoded (ctf_file_t *fp, uint32_t flag, const char *name,
! 1189: const ctf_encoding_t *ep)
! 1190: {
! 1191: ctf_id_t type = 0;
! 1192:
! 1193: /* First, create the enum if need be, using most of the same machinery as
! 1194: ctf_add_enum(), to ensure that we do not allow things past that are not
! 1195: enums or forwards to them. (This includes other slices: you cannot slice a
! 1196: slice, which would be a useless thing to do anyway.) */
! 1197:
! 1198: if (name != NULL)
! 1199: type = ctf_lookup_by_rawname (fp, CTF_K_ENUM, name);
! 1200:
! 1201: if (type != 0)
! 1202: {
! 1203: if ((ctf_type_kind (fp, type) != CTF_K_FORWARD) &&
! 1204: (ctf_type_kind_unsliced (fp, type) != CTF_K_ENUM))
! 1205: return (ctf_set_errno (fp, ECTF_NOTINTFP));
! 1206: }
! 1207: else if ((type = ctf_add_enum (fp, flag, name)) == CTF_ERR)
! 1208: return CTF_ERR; /* errno is set for us. */
! 1209:
! 1210: /* Now attach a suitable slice to it. */
! 1211:
! 1212: return ctf_add_slice (fp, flag, type, ep);
! 1213: }
! 1214:
! 1215: ctf_id_t
! 1216: ctf_add_forward (ctf_file_t *fp, uint32_t flag, const char *name,
! 1217: uint32_t kind)
! 1218: {
! 1219: ctf_dtdef_t *dtd;
! 1220: ctf_id_t type = 0;
! 1221:
! 1222: if (kind != CTF_K_STRUCT && kind != CTF_K_UNION && kind != CTF_K_ENUM)
! 1223: return (ctf_set_errno (fp, ECTF_NOTSUE));
! 1224:
! 1225: /* If the type is already defined or exists as a forward tag, just
! 1226: return the ctf_id_t of the existing definition. */
! 1227:
! 1228: if (name != NULL)
! 1229: type = ctf_lookup_by_rawname (fp, kind, name);
! 1230:
! 1231: if ((type = ctf_add_generic (fp, flag, name, CTF_K_FORWARD,&dtd)) == CTF_ERR)
! 1232: return CTF_ERR; /* errno is set for us. */
! 1233:
! 1234: dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_FORWARD, flag, 0);
! 1235: dtd->dtd_data.ctt_type = kind;
! 1236:
! 1237: return type;
! 1238: }
! 1239:
! 1240: ctf_id_t
! 1241: ctf_add_typedef (ctf_file_t *fp, uint32_t flag, const char *name,
! 1242: ctf_id_t ref)
! 1243: {
! 1244: ctf_dtdef_t *dtd;
! 1245: ctf_id_t type;
! 1246: ctf_file_t *tmp = fp;
! 1247:
! 1248: if (ref == CTF_ERR || ref > CTF_MAX_TYPE)
! 1249: return (ctf_set_errno (fp, EINVAL));
! 1250:
! 1251: if (ctf_lookup_by_id (&tmp, ref) == NULL)
! 1252: return CTF_ERR; /* errno is set for us. */
! 1253:
! 1254: if ((type = ctf_add_generic (fp, flag, name, CTF_K_TYPEDEF,
! 1255: &dtd)) == CTF_ERR)
! 1256: return CTF_ERR; /* errno is set for us. */
! 1257:
! 1258: dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_TYPEDEF, flag, 0);
! 1259: dtd->dtd_data.ctt_type = (uint32_t) ref;
! 1260:
! 1261: return type;
! 1262: }
! 1263:
! 1264: ctf_id_t
! 1265: ctf_add_volatile (ctf_file_t *fp, uint32_t flag, ctf_id_t ref)
! 1266: {
! 1267: return (ctf_add_reftype (fp, flag, ref, CTF_K_VOLATILE));
! 1268: }
! 1269:
! 1270: ctf_id_t
! 1271: ctf_add_const (ctf_file_t *fp, uint32_t flag, ctf_id_t ref)
! 1272: {
! 1273: return (ctf_add_reftype (fp, flag, ref, CTF_K_CONST));
! 1274: }
! 1275:
! 1276: ctf_id_t
! 1277: ctf_add_restrict (ctf_file_t *fp, uint32_t flag, ctf_id_t ref)
! 1278: {
! 1279: return (ctf_add_reftype (fp, flag, ref, CTF_K_RESTRICT));
! 1280: }
! 1281:
! 1282: int
! 1283: ctf_add_enumerator (ctf_file_t *fp, ctf_id_t enid, const char *name,
! 1284: int value)
! 1285: {
! 1286: ctf_dtdef_t *dtd = ctf_dtd_lookup (fp, enid);
! 1287: ctf_dmdef_t *dmd;
! 1288:
! 1289: uint32_t kind, vlen, root;
! 1290: char *s;
! 1291:
! 1292: if (name == NULL)
! 1293: return (ctf_set_errno (fp, EINVAL));
! 1294:
! 1295: if (!(fp->ctf_flags & LCTF_RDWR))
! 1296: return (ctf_set_errno (fp, ECTF_RDONLY));
! 1297:
! 1298: if (dtd == NULL)
! 1299: return (ctf_set_errno (fp, ECTF_BADID));
! 1300:
! 1301: kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
! 1302: root = LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info);
! 1303: vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
! 1304:
! 1305: if (kind != CTF_K_ENUM)
! 1306: return (ctf_set_errno (fp, ECTF_NOTENUM));
! 1307:
! 1308: if (vlen == CTF_MAX_VLEN)
! 1309: return (ctf_set_errno (fp, ECTF_DTFULL));
! 1310:
! 1311: for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
! 1312: dmd != NULL; dmd = ctf_list_next (dmd))
! 1313: {
! 1314: if (strcmp (dmd->dmd_name, name) == 0)
! 1315: return (ctf_set_errno (fp, ECTF_DUPLICATE));
! 1316: }
! 1317:
! 1318: if ((dmd = malloc (sizeof (ctf_dmdef_t))) == NULL)
! 1319: return (ctf_set_errno (fp, EAGAIN));
! 1320:
! 1321: if ((s = strdup (name)) == NULL)
! 1322: {
! 1323: free (dmd);
! 1324: return (ctf_set_errno (fp, EAGAIN));
! 1325: }
! 1326:
! 1327: dmd->dmd_name = s;
! 1328: dmd->dmd_type = CTF_ERR;
! 1329: dmd->dmd_offset = 0;
! 1330: dmd->dmd_value = value;
! 1331:
! 1332: dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, root, vlen + 1);
! 1333: ctf_list_append (&dtd->dtd_u.dtu_members, dmd);
! 1334:
! 1335: fp->ctf_flags |= LCTF_DIRTY;
! 1336:
! 1337: return 0;
! 1338: }
! 1339:
! 1340: int
! 1341: ctf_add_member_offset (ctf_file_t *fp, ctf_id_t souid, const char *name,
! 1342: ctf_id_t type, unsigned long bit_offset)
! 1343: {
! 1344: ctf_dtdef_t *dtd = ctf_dtd_lookup (fp, souid);
! 1345: ctf_dmdef_t *dmd;
! 1346:
! 1347: ssize_t msize, malign, ssize;
! 1348: uint32_t kind, vlen, root;
! 1349: char *s = NULL;
! 1350:
! 1351: if (!(fp->ctf_flags & LCTF_RDWR))
! 1352: return (ctf_set_errno (fp, ECTF_RDONLY));
! 1353:
! 1354: if (dtd == NULL)
! 1355: return (ctf_set_errno (fp, ECTF_BADID));
! 1356:
! 1357: kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
! 1358: root = LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info);
! 1359: vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
! 1360:
! 1361: if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
! 1362: return (ctf_set_errno (fp, ECTF_NOTSOU));
! 1363:
! 1364: if (vlen == CTF_MAX_VLEN)
! 1365: return (ctf_set_errno (fp, ECTF_DTFULL));
! 1366:
! 1367: if (name != NULL)
! 1368: {
! 1369: for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
! 1370: dmd != NULL; dmd = ctf_list_next (dmd))
! 1371: {
! 1372: if (dmd->dmd_name != NULL && strcmp (dmd->dmd_name, name) == 0)
! 1373: return (ctf_set_errno (fp, ECTF_DUPLICATE));
! 1374: }
! 1375: }
! 1376:
! 1377: if ((msize = ctf_type_size (fp, type)) < 0 ||
! 1378: (malign = ctf_type_align (fp, type)) < 0)
! 1379: return -1; /* errno is set for us. */
! 1380:
! 1381: if ((dmd = malloc (sizeof (ctf_dmdef_t))) == NULL)
! 1382: return (ctf_set_errno (fp, EAGAIN));
! 1383:
! 1384: if (name != NULL && (s = strdup (name)) == NULL)
! 1385: {
! 1386: free (dmd);
! 1387: return (ctf_set_errno (fp, EAGAIN));
! 1388: }
! 1389:
! 1390: dmd->dmd_name = s;
! 1391: dmd->dmd_type = type;
! 1392: dmd->dmd_value = -1;
! 1393:
! 1394: if (kind == CTF_K_STRUCT && vlen != 0)
! 1395: {
! 1396: if (bit_offset == (unsigned long) - 1)
! 1397: {
! 1398: /* Natural alignment. */
! 1399:
! 1400: ctf_dmdef_t *lmd = ctf_list_prev (&dtd->dtd_u.dtu_members);
! 1401: ctf_id_t ltype = ctf_type_resolve (fp, lmd->dmd_type);
! 1402: size_t off = lmd->dmd_offset;
! 1403:
! 1404: ctf_encoding_t linfo;
! 1405: ssize_t lsize;
! 1406:
! 1407: if (ctf_type_encoding (fp, ltype, &linfo) == 0)
! 1408: off += linfo.cte_bits;
! 1409: else if ((lsize = ctf_type_size (fp, ltype)) > 0)
! 1410: off += lsize * CHAR_BIT;
! 1411:
! 1412: /* Round up the offset of the end of the last member to
! 1413: the next byte boundary, convert 'off' to bytes, and
! 1414: then round it up again to the next multiple of the
! 1415: alignment required by the new member. Finally,
! 1416: convert back to bits and store the result in
! 1417: dmd_offset. Technically we could do more efficient
! 1418: packing if the new member is a bit-field, but we're
! 1419: the "compiler" and ANSI says we can do as we choose. */
! 1420:
! 1421: off = roundup (off, CHAR_BIT) / CHAR_BIT;
! 1422: off = roundup (off, MAX (malign, 1));
! 1423: dmd->dmd_offset = off * CHAR_BIT;
! 1424: ssize = off + msize;
! 1425: }
! 1426: else
! 1427: {
! 1428: /* Specified offset in bits. */
! 1429:
! 1430: dmd->dmd_offset = bit_offset;
! 1431: ssize = ctf_get_ctt_size (fp, &dtd->dtd_data, NULL, NULL);
! 1432: ssize = MAX (ssize, ((signed) bit_offset / CHAR_BIT) + msize);
! 1433: }
! 1434: }
! 1435: else
! 1436: {
! 1437: dmd->dmd_offset = 0;
! 1438: ssize = ctf_get_ctt_size (fp, &dtd->dtd_data, NULL, NULL);
! 1439: ssize = MAX (ssize, msize);
! 1440: }
! 1441:
! 1442: if ((size_t) ssize > CTF_MAX_SIZE)
! 1443: {
! 1444: dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
! 1445: dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (ssize);
! 1446: dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (ssize);
! 1447: }
! 1448: else
! 1449: dtd->dtd_data.ctt_size = (uint32_t) ssize;
! 1450:
! 1451: dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, root, vlen + 1);
! 1452: ctf_list_append (&dtd->dtd_u.dtu_members, dmd);
! 1453:
! 1454: fp->ctf_flags |= LCTF_DIRTY;
! 1455: return 0;
! 1456: }
! 1457:
! 1458: int
! 1459: ctf_add_member_encoded (ctf_file_t *fp, ctf_id_t souid, const char *name,
! 1460: ctf_id_t type, unsigned long bit_offset,
! 1461: const ctf_encoding_t encoding)
! 1462: {
! 1463: ctf_dtdef_t *dtd = ctf_dtd_lookup (fp, type);
! 1464: int kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
! 1465: int otype = type;
! 1466:
! 1467: if ((kind != CTF_K_INTEGER) && (kind != CTF_K_FLOAT) && (kind != CTF_K_ENUM))
! 1468: return (ctf_set_errno (fp, ECTF_NOTINTFP));
! 1469:
! 1470: if ((type = ctf_add_slice (fp, CTF_ADD_NONROOT, otype, &encoding)) == CTF_ERR)
! 1471: return -1; /* errno is set for us. */
! 1472:
! 1473: return ctf_add_member_offset (fp, souid, name, type, bit_offset);
! 1474: }
! 1475:
! 1476: int
! 1477: ctf_add_member (ctf_file_t *fp, ctf_id_t souid, const char *name,
! 1478: ctf_id_t type)
! 1479: {
! 1480: return ctf_add_member_offset (fp, souid, name, type, (unsigned long) - 1);
! 1481: }
! 1482:
! 1483: int
! 1484: ctf_add_variable (ctf_file_t *fp, const char *name, ctf_id_t ref)
! 1485: {
! 1486: ctf_dvdef_t *dvd;
! 1487: ctf_file_t *tmp = fp;
! 1488:
! 1489: if (!(fp->ctf_flags & LCTF_RDWR))
! 1490: return (ctf_set_errno (fp, ECTF_RDONLY));
! 1491:
! 1492: if (ctf_dvd_lookup (fp, name) != NULL)
! 1493: return (ctf_set_errno (fp, ECTF_DUPLICATE));
! 1494:
! 1495: if (ctf_lookup_by_id (&tmp, ref) == NULL)
! 1496: return -1; /* errno is set for us. */
! 1497:
! 1498: /* Make sure this type is representable. */
! 1499: if ((ctf_type_resolve (fp, ref) == CTF_ERR)
! 1500: && (ctf_errno (fp) == ECTF_NONREPRESENTABLE))
! 1501: return -1;
! 1502:
! 1503: if ((dvd = malloc (sizeof (ctf_dvdef_t))) == NULL)
! 1504: return (ctf_set_errno (fp, EAGAIN));
! 1505:
! 1506: if (name != NULL && (dvd->dvd_name = strdup (name)) == NULL)
! 1507: {
! 1508: free (dvd);
! 1509: return (ctf_set_errno (fp, EAGAIN));
! 1510: }
! 1511: dvd->dvd_type = ref;
! 1512: dvd->dvd_snapshots = fp->ctf_snapshots;
! 1513:
! 1514: if (ctf_dvd_insert (fp, dvd) < 0)
! 1515: {
! 1516: free (dvd->dvd_name);
! 1517: free (dvd);
! 1518: return -1; /* errno is set for us. */
! 1519: }
! 1520:
! 1521: fp->ctf_flags |= LCTF_DIRTY;
! 1522: return 0;
! 1523: }
! 1524:
! 1525: static int
! 1526: enumcmp (const char *name, int value, void *arg)
! 1527: {
! 1528: ctf_bundle_t *ctb = arg;
! 1529: int bvalue;
! 1530:
! 1531: if (ctf_enum_value (ctb->ctb_file, ctb->ctb_type, name, &bvalue) < 0)
! 1532: {
! 1533: ctf_dprintf ("Conflict due to member %s iteration error: %s.\n", name,
! 1534: ctf_errmsg (ctf_errno (ctb->ctb_file)));
! 1535: return 1;
! 1536: }
! 1537: if (value != bvalue)
! 1538: {
! 1539: ctf_dprintf ("Conflict due to value change: %i versus %i\n",
! 1540: value, bvalue);
! 1541: return 1;
! 1542: }
! 1543: return 0;
! 1544: }
! 1545:
! 1546: static int
! 1547: enumadd (const char *name, int value, void *arg)
! 1548: {
! 1549: ctf_bundle_t *ctb = arg;
! 1550:
! 1551: return (ctf_add_enumerator (ctb->ctb_file, ctb->ctb_type,
! 1552: name, value) < 0);
! 1553: }
! 1554:
! 1555: static int
! 1556: membcmp (const char *name, ctf_id_t type _libctf_unused_, unsigned long offset,
! 1557: void *arg)
! 1558: {
! 1559: ctf_bundle_t *ctb = arg;
! 1560: ctf_membinfo_t ctm;
! 1561:
! 1562: if (ctf_member_info (ctb->ctb_file, ctb->ctb_type, name, &ctm) < 0)
! 1563: {
! 1564: ctf_dprintf ("Conflict due to member %s iteration error: %s.\n", name,
! 1565: ctf_errmsg (ctf_errno (ctb->ctb_file)));
! 1566: return 1;
! 1567: }
! 1568: if (ctm.ctm_offset != offset)
! 1569: {
! 1570: ctf_dprintf ("Conflict due to member %s offset change: "
! 1571: "%lx versus %lx\n", name, ctm.ctm_offset, offset);
! 1572: return 1;
! 1573: }
! 1574: return 0;
! 1575: }
! 1576:
! 1577: static int
! 1578: membadd (const char *name, ctf_id_t type, unsigned long offset, void *arg)
! 1579: {
! 1580: ctf_bundle_t *ctb = arg;
! 1581: ctf_dmdef_t *dmd;
! 1582: char *s = NULL;
! 1583:
! 1584: if ((dmd = malloc (sizeof (ctf_dmdef_t))) == NULL)
! 1585: return (ctf_set_errno (ctb->ctb_file, EAGAIN));
! 1586:
! 1587: if (name != NULL && (s = strdup (name)) == NULL)
! 1588: {
! 1589: free (dmd);
! 1590: return (ctf_set_errno (ctb->ctb_file, EAGAIN));
! 1591: }
! 1592:
! 1593: /* For now, dmd_type is copied as the src_fp's type; it is reset to an
! 1594: equivalent dst_fp type by a final loop in ctf_add_type(), below. */
! 1595: dmd->dmd_name = s;
! 1596: dmd->dmd_type = type;
! 1597: dmd->dmd_offset = offset;
! 1598: dmd->dmd_value = -1;
! 1599:
! 1600: ctf_list_append (&ctb->ctb_dtd->dtd_u.dtu_members, dmd);
! 1601:
! 1602: ctb->ctb_file->ctf_flags |= LCTF_DIRTY;
! 1603: return 0;
! 1604: }
! 1605:
! 1606: /* The ctf_add_type routine is used to copy a type from a source CTF container
! 1607: to a dynamic destination container. This routine operates recursively by
! 1608: following the source type's links and embedded member types. If the
! 1609: destination container already contains a named type which has the same
! 1610: attributes, then we succeed and return this type but no changes occur. */
! 1611: static ctf_id_t
! 1612: ctf_add_type_internal (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type,
! 1613: ctf_file_t *proc_tracking_fp)
! 1614: {
! 1615: ctf_id_t dst_type = CTF_ERR;
! 1616: uint32_t dst_kind = CTF_K_UNKNOWN;
! 1617: ctf_file_t *tmp_fp = dst_fp;
! 1618: ctf_id_t tmp;
! 1619:
! 1620: const char *name;
! 1621: uint32_t kind, forward_kind, flag, vlen;
! 1622:
! 1623: const ctf_type_t *src_tp, *dst_tp;
! 1624: ctf_bundle_t src, dst;
! 1625: ctf_encoding_t src_en, dst_en;
! 1626: ctf_arinfo_t src_ar, dst_ar;
! 1627:
! 1628: ctf_funcinfo_t ctc;
! 1629:
! 1630: ctf_id_t orig_src_type = src_type;
! 1631:
! 1632: if (!(dst_fp->ctf_flags & LCTF_RDWR))
! 1633: return (ctf_set_errno (dst_fp, ECTF_RDONLY));
! 1634:
! 1635: if ((src_tp = ctf_lookup_by_id (&src_fp, src_type)) == NULL)
! 1636: return (ctf_set_errno (dst_fp, ctf_errno (src_fp)));
! 1637:
! 1638: if ((ctf_type_resolve (src_fp, src_type) == CTF_ERR)
! 1639: && (ctf_errno (src_fp) == ECTF_NONREPRESENTABLE))
! 1640: return (ctf_set_errno (dst_fp, ECTF_NONREPRESENTABLE));
! 1641:
! 1642: name = ctf_strptr (src_fp, src_tp->ctt_name);
! 1643: kind = LCTF_INFO_KIND (src_fp, src_tp->ctt_info);
! 1644: flag = LCTF_INFO_ISROOT (src_fp, src_tp->ctt_info);
! 1645: vlen = LCTF_INFO_VLEN (src_fp, src_tp->ctt_info);
! 1646:
! 1647: /* If this is a type we are currently in the middle of adding, hand it
! 1648: straight back. (This lets us handle self-referential structures without
! 1649: considering forwards and empty structures the same as their completed
! 1650: forms.) */
! 1651:
! 1652: tmp = ctf_type_mapping (src_fp, src_type, &tmp_fp);
! 1653:
! 1654: if (tmp != 0)
! 1655: {
! 1656: if (ctf_dynhash_lookup (proc_tracking_fp->ctf_add_processing,
! 1657: (void *) (uintptr_t) src_type))
! 1658: return tmp;
! 1659:
! 1660: /* If this type has already been added from this container, and is the same
! 1661: kind and (if a struct or union) has the same number of members, hand it
! 1662: straight back. */
! 1663:
! 1664: if ((ctf_type_kind_unsliced (tmp_fp, tmp) == (int) kind)
! 1665: && (kind == CTF_K_STRUCT || kind == CTF_K_UNION
! 1666: || kind == CTF_K_ENUM))
! 1667: {
! 1668: if ((dst_tp = ctf_lookup_by_id (&tmp_fp, dst_type)) != NULL)
! 1669: if (vlen == LCTF_INFO_VLEN (tmp_fp, dst_tp->ctt_info))
! 1670: return tmp;
! 1671: }
! 1672: }
! 1673:
! 1674: forward_kind = kind;
! 1675: if (kind == CTF_K_FORWARD)
! 1676: forward_kind = src_tp->ctt_type;
! 1677:
! 1678: /* If the source type has a name and is a root type (visible at the
! 1679: top-level scope), lookup the name in the destination container and
! 1680: verify that it is of the same kind before we do anything else. */
! 1681:
! 1682: if ((flag & CTF_ADD_ROOT) && name[0] != '\0'
! 1683: && (tmp = ctf_lookup_by_rawname (dst_fp, forward_kind, name)) != 0)
! 1684: {
! 1685: dst_type = tmp;
! 1686: dst_kind = ctf_type_kind_unsliced (dst_fp, dst_type);
! 1687: }
! 1688:
! 1689: /* If an identically named dst_type exists, fail with ECTF_CONFLICT
! 1690: unless dst_type is a forward declaration and src_type is a struct,
! 1691: union, or enum (i.e. the definition of the previous forward decl).
! 1692:
! 1693: We also allow addition in the opposite order (addition of a forward when a
! 1694: struct, union, or enum already exists), which is a NOP and returns the
! 1695: already-present struct, union, or enum. */
! 1696:
! 1697: if (dst_type != CTF_ERR && dst_kind != kind)
! 1698: {
! 1699: if (kind == CTF_K_FORWARD
! 1700: && (dst_kind == CTF_K_ENUM || dst_kind == CTF_K_STRUCT
! 1701: || dst_kind == CTF_K_UNION))
! 1702: {
! 1703: ctf_add_type_mapping (src_fp, src_type, dst_fp, dst_type);
! 1704: return dst_type;
! 1705: }
! 1706:
! 1707: if (dst_kind != CTF_K_FORWARD
! 1708: || (kind != CTF_K_ENUM && kind != CTF_K_STRUCT
! 1709: && kind != CTF_K_UNION))
! 1710: {
! 1711: ctf_dprintf ("Conflict for type %s: kinds differ, new: %i; "
! 1712: "old (ID %lx): %i\n", name, kind, dst_type, dst_kind);
! 1713: return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
! 1714: }
! 1715: }
! 1716:
! 1717: /* We take special action for an integer, float, or slice since it is
! 1718: described not only by its name but also its encoding. For integers,
! 1719: bit-fields exploit this degeneracy. */
! 1720:
! 1721: if (kind == CTF_K_INTEGER || kind == CTF_K_FLOAT || kind == CTF_K_SLICE)
! 1722: {
! 1723: if (ctf_type_encoding (src_fp, src_type, &src_en) != 0)
! 1724: return (ctf_set_errno (dst_fp, ctf_errno (src_fp)));
! 1725:
! 1726: if (dst_type != CTF_ERR)
! 1727: {
! 1728: ctf_file_t *fp = dst_fp;
! 1729:
! 1730: if ((dst_tp = ctf_lookup_by_id (&fp, dst_type)) == NULL)
! 1731: return CTF_ERR;
! 1732:
! 1733: if (ctf_type_encoding (dst_fp, dst_type, &dst_en) != 0)
! 1734: return CTF_ERR; /* errno set for us. */
! 1735:
! 1736: if (LCTF_INFO_ISROOT (fp, dst_tp->ctt_info) & CTF_ADD_ROOT)
! 1737: {
! 1738: /* The type that we found in the hash is also root-visible. If
! 1739: the two types match then use the existing one; otherwise,
! 1740: declare a conflict. Note: slices are not certain to match
! 1741: even if there is no conflict: we must check the contained type
! 1742: too. */
! 1743:
! 1744: if (memcmp (&src_en, &dst_en, sizeof (ctf_encoding_t)) == 0)
! 1745: {
! 1746: if (kind != CTF_K_SLICE)
! 1747: {
! 1748: ctf_add_type_mapping (src_fp, src_type, dst_fp, dst_type);
! 1749: return dst_type;
! 1750: }
! 1751: }
! 1752: else
! 1753: {
! 1754: return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
! 1755: }
! 1756: }
! 1757: else
! 1758: {
! 1759: /* We found a non-root-visible type in the hash. If its encoding
! 1760: is the same, we can reuse it, unless it is a slice. */
! 1761:
! 1762: if (memcmp (&src_en, &dst_en, sizeof (ctf_encoding_t)) == 0)
! 1763: {
! 1764: if (kind != CTF_K_SLICE)
! 1765: {
! 1766: ctf_add_type_mapping (src_fp, src_type, dst_fp, dst_type);
! 1767: return dst_type;
! 1768: }
! 1769: }
! 1770: }
! 1771: }
! 1772: }
! 1773:
! 1774: src.ctb_file = src_fp;
! 1775: src.ctb_type = src_type;
! 1776: src.ctb_dtd = NULL;
! 1777:
! 1778: dst.ctb_file = dst_fp;
! 1779: dst.ctb_type = dst_type;
! 1780: dst.ctb_dtd = NULL;
! 1781:
! 1782: /* Now perform kind-specific processing. If dst_type is CTF_ERR, then we add
! 1783: a new type with the same properties as src_type to dst_fp. If dst_type is
! 1784: not CTF_ERR, then we verify that dst_type has the same attributes as
! 1785: src_type. We recurse for embedded references. Before we start, we note
! 1786: that we are processing this type, to prevent infinite recursion: we do not
! 1787: re-process any type that appears in this list. The list is emptied
! 1788: wholesale at the end of processing everything in this recursive stack. */
! 1789:
! 1790: if (ctf_dynhash_insert (proc_tracking_fp->ctf_add_processing,
! 1791: (void *) (uintptr_t) src_type, (void *) 1) < 0)
! 1792: return ctf_set_errno (dst_fp, ENOMEM);
! 1793:
! 1794: switch (kind)
! 1795: {
! 1796: case CTF_K_INTEGER:
! 1797: /* If we found a match we will have either returned it or declared a
! 1798: conflict. */
! 1799: dst_type = ctf_add_integer (dst_fp, flag, name, &src_en);
! 1800: break;
! 1801:
! 1802: case CTF_K_FLOAT:
! 1803: /* If we found a match we will have either returned it or declared a
! 1804: conflict. */
! 1805: dst_type = ctf_add_float (dst_fp, flag, name, &src_en);
! 1806: break;
! 1807:
! 1808: case CTF_K_SLICE:
! 1809: /* We have checked for conflicting encodings: now try to add the
! 1810: contained type. */
! 1811: src_type = ctf_type_reference (src_fp, src_type);
! 1812: src_type = ctf_add_type_internal (dst_fp, src_fp, src_type,
! 1813: proc_tracking_fp);
! 1814:
! 1815: if (src_type == CTF_ERR)
! 1816: return CTF_ERR; /* errno is set for us. */
! 1817:
! 1818: dst_type = ctf_add_slice (dst_fp, flag, src_type, &src_en);
! 1819: break;
! 1820:
! 1821: case CTF_K_POINTER:
! 1822: case CTF_K_VOLATILE:
! 1823: case CTF_K_CONST:
! 1824: case CTF_K_RESTRICT:
! 1825: src_type = ctf_type_reference (src_fp, src_type);
! 1826: src_type = ctf_add_type_internal (dst_fp, src_fp, src_type,
! 1827: proc_tracking_fp);
! 1828:
! 1829: if (src_type == CTF_ERR)
! 1830: return CTF_ERR; /* errno is set for us. */
! 1831:
! 1832: dst_type = ctf_add_reftype (dst_fp, flag, src_type, kind);
! 1833: break;
! 1834:
! 1835: case CTF_K_ARRAY:
! 1836: if (ctf_array_info (src_fp, src_type, &src_ar) != 0)
! 1837: return (ctf_set_errno (dst_fp, ctf_errno (src_fp)));
! 1838:
! 1839: src_ar.ctr_contents =
! 1840: ctf_add_type_internal (dst_fp, src_fp, src_ar.ctr_contents,
! 1841: proc_tracking_fp);
! 1842: src_ar.ctr_index = ctf_add_type_internal (dst_fp, src_fp,
! 1843: src_ar.ctr_index,
! 1844: proc_tracking_fp);
! 1845: src_ar.ctr_nelems = src_ar.ctr_nelems;
! 1846:
! 1847: if (src_ar.ctr_contents == CTF_ERR || src_ar.ctr_index == CTF_ERR)
! 1848: return CTF_ERR; /* errno is set for us. */
! 1849:
! 1850: if (dst_type != CTF_ERR)
! 1851: {
! 1852: if (ctf_array_info (dst_fp, dst_type, &dst_ar) != 0)
! 1853: return CTF_ERR; /* errno is set for us. */
! 1854:
! 1855: if (memcmp (&src_ar, &dst_ar, sizeof (ctf_arinfo_t)))
! 1856: {
! 1857: ctf_dprintf ("Conflict for type %s against ID %lx: "
! 1858: "array info differs, old %lx/%lx/%x; "
! 1859: "new: %lx/%lx/%x\n", name, dst_type,
! 1860: src_ar.ctr_contents, src_ar.ctr_index,
! 1861: src_ar.ctr_nelems, dst_ar.ctr_contents,
! 1862: dst_ar.ctr_index, dst_ar.ctr_nelems);
! 1863: return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
! 1864: }
! 1865: }
! 1866: else
! 1867: dst_type = ctf_add_array (dst_fp, flag, &src_ar);
! 1868: break;
! 1869:
! 1870: case CTF_K_FUNCTION:
! 1871: ctc.ctc_return = ctf_add_type_internal (dst_fp, src_fp,
! 1872: src_tp->ctt_type,
! 1873: proc_tracking_fp);
! 1874: ctc.ctc_argc = 0;
! 1875: ctc.ctc_flags = 0;
! 1876:
! 1877: if (ctc.ctc_return == CTF_ERR)
! 1878: return CTF_ERR; /* errno is set for us. */
! 1879:
! 1880: dst_type = ctf_add_function (dst_fp, flag, &ctc, NULL);
! 1881: break;
! 1882:
! 1883: case CTF_K_STRUCT:
! 1884: case CTF_K_UNION:
! 1885: {
! 1886: ctf_dmdef_t *dmd;
! 1887: int errs = 0;
! 1888: size_t size;
! 1889: ssize_t ssize;
! 1890: ctf_dtdef_t *dtd;
! 1891:
! 1892: /* Technically to match a struct or union we need to check both
! 1893: ways (src members vs. dst, dst members vs. src) but we make
! 1894: this more optimal by only checking src vs. dst and comparing
! 1895: the total size of the structure (which we must do anyway)
! 1896: which covers the possibility of dst members not in src.
! 1897: This optimization can be defeated for unions, but is so
! 1898: pathological as to render it irrelevant for our purposes. */
! 1899:
! 1900: if (dst_type != CTF_ERR && kind != CTF_K_FORWARD
! 1901: && dst_kind != CTF_K_FORWARD)
! 1902: {
! 1903: if (ctf_type_size (src_fp, src_type) !=
! 1904: ctf_type_size (dst_fp, dst_type))
! 1905: {
! 1906: ctf_dprintf ("Conflict for type %s against ID %lx: "
! 1907: "union size differs, old %li, new %li\n",
! 1908: name, dst_type,
! 1909: (long) ctf_type_size (src_fp, src_type),
! 1910: (long) ctf_type_size (dst_fp, dst_type));
! 1911: return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
! 1912: }
! 1913:
! 1914: if (ctf_member_iter (src_fp, src_type, membcmp, &dst))
! 1915: {
! 1916: ctf_dprintf ("Conflict for type %s against ID %lx: "
! 1917: "members differ, see above\n", name, dst_type);
! 1918: return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
! 1919: }
! 1920:
! 1921: break;
! 1922: }
! 1923:
! 1924: /* Unlike the other cases, copying structs and unions is done
! 1925: manually so as to avoid repeated lookups in ctf_add_member
! 1926: and to ensure the exact same member offsets as in src_type. */
! 1927:
! 1928: dst_type = ctf_add_generic (dst_fp, flag, name, kind, &dtd);
! 1929: if (dst_type == CTF_ERR)
! 1930: return CTF_ERR; /* errno is set for us. */
! 1931:
! 1932: dst.ctb_type = dst_type;
! 1933: dst.ctb_dtd = dtd;
! 1934:
! 1935: /* Pre-emptively add this struct to the type mapping so that
! 1936: structures that refer to themselves work. */
! 1937: ctf_add_type_mapping (src_fp, src_type, dst_fp, dst_type);
! 1938:
! 1939: if (ctf_member_iter (src_fp, src_type, membadd, &dst) != 0)
! 1940: errs++; /* Increment errs and fail at bottom of case. */
! 1941:
! 1942: if ((ssize = ctf_type_size (src_fp, src_type)) < 0)
! 1943: return CTF_ERR; /* errno is set for us. */
! 1944:
! 1945: size = (size_t) ssize;
! 1946: if (size > CTF_MAX_SIZE)
! 1947: {
! 1948: dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
! 1949: dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (size);
! 1950: dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (size);
! 1951: }
! 1952: else
! 1953: dtd->dtd_data.ctt_size = (uint32_t) size;
! 1954:
! 1955: dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, flag, vlen);
! 1956:
! 1957: /* Make a final pass through the members changing each dmd_type (a
! 1958: src_fp type) to an equivalent type in dst_fp. We pass through all
! 1959: members, leaving any that fail set to CTF_ERR, unless they fail
! 1960: because they are marking a member of type not representable in this
! 1961: version of CTF, in which case we just want to silently omit them:
! 1962: no consumer can do anything with them anyway. */
! 1963: for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
! 1964: dmd != NULL; dmd = ctf_list_next (dmd))
! 1965: {
! 1966: ctf_file_t *dst = dst_fp;
! 1967: ctf_id_t memb_type;
! 1968:
! 1969: memb_type = ctf_type_mapping (src_fp, dmd->dmd_type, &dst);
! 1970: if (memb_type == 0)
! 1971: {
! 1972: if ((dmd->dmd_type =
! 1973: ctf_add_type_internal (dst_fp, src_fp, dmd->dmd_type,
! 1974: proc_tracking_fp)) == CTF_ERR)
! 1975: {
! 1976: if (ctf_errno (dst_fp) != ECTF_NONREPRESENTABLE)
! 1977: errs++;
! 1978: }
! 1979: }
! 1980: else
! 1981: dmd->dmd_type = memb_type;
! 1982: }
! 1983:
! 1984: if (errs)
! 1985: return CTF_ERR; /* errno is set for us. */
! 1986: break;
! 1987: }
! 1988:
! 1989: case CTF_K_ENUM:
! 1990: if (dst_type != CTF_ERR && kind != CTF_K_FORWARD
! 1991: && dst_kind != CTF_K_FORWARD)
! 1992: {
! 1993: if (ctf_enum_iter (src_fp, src_type, enumcmp, &dst)
! 1994: || ctf_enum_iter (dst_fp, dst_type, enumcmp, &src))
! 1995: {
! 1996: ctf_dprintf ("Conflict for enum %s against ID %lx: "
! 1997: "members differ, see above\n", name, dst_type);
! 1998: return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
! 1999: }
! 2000: }
! 2001: else
! 2002: {
! 2003: dst_type = ctf_add_enum (dst_fp, flag, name);
! 2004: if ((dst.ctb_type = dst_type) == CTF_ERR
! 2005: || ctf_enum_iter (src_fp, src_type, enumadd, &dst))
! 2006: return CTF_ERR; /* errno is set for us */
! 2007: }
! 2008: break;
! 2009:
! 2010: case CTF_K_FORWARD:
! 2011: if (dst_type == CTF_ERR)
! 2012: dst_type = ctf_add_forward (dst_fp, flag, name, forward_kind);
! 2013: break;
! 2014:
! 2015: case CTF_K_TYPEDEF:
! 2016: src_type = ctf_type_reference (src_fp, src_type);
! 2017: src_type = ctf_add_type_internal (dst_fp, src_fp, src_type,
! 2018: proc_tracking_fp);
! 2019:
! 2020: if (src_type == CTF_ERR)
! 2021: return CTF_ERR; /* errno is set for us. */
! 2022:
! 2023: /* If dst_type is not CTF_ERR at this point, we should check if
! 2024: ctf_type_reference(dst_fp, dst_type) != src_type and if so fail with
! 2025: ECTF_CONFLICT. However, this causes problems with bitness typedefs
! 2026: that vary based on things like if 32-bit then pid_t is int otherwise
! 2027: long. We therefore omit this check and assume that if the identically
! 2028: named typedef already exists in dst_fp, it is correct or
! 2029: equivalent. */
! 2030:
! 2031: if (dst_type == CTF_ERR)
! 2032: dst_type = ctf_add_typedef (dst_fp, flag, name, src_type);
! 2033:
! 2034: break;
! 2035:
! 2036: default:
! 2037: return (ctf_set_errno (dst_fp, ECTF_CORRUPT));
! 2038: }
! 2039:
! 2040: if (dst_type != CTF_ERR)
! 2041: ctf_add_type_mapping (src_fp, orig_src_type, dst_fp, dst_type);
! 2042: return dst_type;
! 2043: }
! 2044:
! 2045: ctf_id_t
! 2046: ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
! 2047: {
! 2048: ctf_id_t id;
! 2049:
! 2050: if (!src_fp->ctf_add_processing)
! 2051: src_fp->ctf_add_processing = ctf_dynhash_create (ctf_hash_integer,
! 2052: ctf_hash_eq_integer,
! 2053: NULL, NULL);
! 2054:
! 2055: /* We store the hash on the source, because it contains only source type IDs:
! 2056: but callers will invariably expect errors to appear on the dest. */
! 2057: if (!src_fp->ctf_add_processing)
! 2058: return (ctf_set_errno (dst_fp, ENOMEM));
! 2059:
! 2060: id = ctf_add_type_internal (dst_fp, src_fp, src_type, src_fp);
! 2061: ctf_dynhash_empty (src_fp->ctf_add_processing);
! 2062:
! 2063: return id;
! 2064: }
! 2065:
! 2066: /* Write the compressed CTF data stream to the specified gzFile descriptor. */
! 2067: int
! 2068: ctf_gzwrite (ctf_file_t *fp, gzFile fd)
! 2069: {
! 2070: const unsigned char *buf;
! 2071: ssize_t resid;
! 2072: ssize_t len;
! 2073:
! 2074: resid = sizeof (ctf_header_t);
! 2075: buf = (unsigned char *) fp->ctf_header;
! 2076: while (resid != 0)
! 2077: {
! 2078: if ((len = gzwrite (fd, buf, resid)) <= 0)
! 2079: return (ctf_set_errno (fp, errno));
! 2080: resid -= len;
! 2081: buf += len;
! 2082: }
! 2083:
! 2084: resid = fp->ctf_size;
! 2085: buf = fp->ctf_buf;
! 2086: while (resid != 0)
! 2087: {
! 2088: if ((len = gzwrite (fd, buf, resid)) <= 0)
! 2089: return (ctf_set_errno (fp, errno));
! 2090: resid -= len;
! 2091: buf += len;
! 2092: }
! 2093:
! 2094: return 0;
! 2095: }
! 2096:
! 2097: /* Compress the specified CTF data stream and write it to the specified file
! 2098: descriptor. */
! 2099: int
! 2100: ctf_compress_write (ctf_file_t *fp, int fd)
! 2101: {
! 2102: unsigned char *buf;
! 2103: unsigned char *bp;
! 2104: ctf_header_t h;
! 2105: ctf_header_t *hp = &h;
! 2106: ssize_t header_len = sizeof (ctf_header_t);
! 2107: ssize_t compress_len;
! 2108: ssize_t len;
! 2109: int rc;
! 2110: int err = 0;
! 2111:
! 2112: if (ctf_serialize (fp) < 0)
! 2113: return -1; /* errno is set for us. */
! 2114:
! 2115: memcpy (hp, fp->ctf_header, header_len);
! 2116: hp->cth_flags |= CTF_F_COMPRESS;
! 2117: compress_len = compressBound (fp->ctf_size);
! 2118:
! 2119: if ((buf = malloc (compress_len)) == NULL)
! 2120: return (ctf_set_errno (fp, ECTF_ZALLOC));
! 2121:
! 2122: if ((rc = compress (buf, (uLongf *) &compress_len,
! 2123: fp->ctf_buf, fp->ctf_size)) != Z_OK)
! 2124: {
! 2125: ctf_dprintf ("zlib deflate err: %s\n", zError (rc));
! 2126: err = ctf_set_errno (fp, ECTF_COMPRESS);
! 2127: goto ret;
! 2128: }
! 2129:
! 2130: while (header_len > 0)
! 2131: {
! 2132: if ((len = write (fd, hp, header_len)) < 0)
! 2133: {
! 2134: err = ctf_set_errno (fp, errno);
! 2135: goto ret;
! 2136: }
! 2137: header_len -= len;
! 2138: hp += len;
! 2139: }
! 2140:
! 2141: bp = buf;
! 2142: while (compress_len > 0)
! 2143: {
! 2144: if ((len = write (fd, bp, compress_len)) < 0)
! 2145: {
! 2146: err = ctf_set_errno (fp, errno);
! 2147: goto ret;
! 2148: }
! 2149: compress_len -= len;
! 2150: bp += len;
! 2151: }
! 2152:
! 2153: ret:
! 2154: free (buf);
! 2155: return err;
! 2156: }
! 2157:
! 2158: /* Optionally compress the specified CTF data stream and return it as a new
! 2159: dynamically-allocated string. */
! 2160: unsigned char *
! 2161: ctf_write_mem (ctf_file_t *fp, size_t *size, size_t threshold)
! 2162: {
! 2163: unsigned char *buf;
! 2164: unsigned char *bp;
! 2165: ctf_header_t *hp;
! 2166: ssize_t header_len = sizeof (ctf_header_t);
! 2167: ssize_t compress_len;
! 2168: int rc;
! 2169:
! 2170: if (ctf_serialize (fp) < 0)
! 2171: return NULL; /* errno is set for us. */
! 2172:
! 2173: compress_len = compressBound (fp->ctf_size);
! 2174: if (fp->ctf_size < threshold)
! 2175: compress_len = fp->ctf_size;
! 2176: if ((buf = malloc (compress_len
! 2177: + sizeof (struct ctf_header))) == NULL)
! 2178: {
! 2179: ctf_set_errno (fp, ENOMEM);
! 2180: return NULL;
! 2181: }
! 2182:
! 2183: hp = (ctf_header_t *) buf;
! 2184: memcpy (hp, fp->ctf_header, header_len);
! 2185: bp = buf + sizeof (struct ctf_header);
! 2186: *size = sizeof (struct ctf_header);
! 2187:
! 2188: if (fp->ctf_size < threshold)
! 2189: {
! 2190: hp->cth_flags &= ~CTF_F_COMPRESS;
! 2191: memcpy (bp, fp->ctf_buf, fp->ctf_size);
! 2192: *size += fp->ctf_size;
! 2193: }
! 2194: else
! 2195: {
! 2196: hp->cth_flags |= CTF_F_COMPRESS;
! 2197: if ((rc = compress (bp, (uLongf *) &compress_len,
! 2198: fp->ctf_buf, fp->ctf_size)) != Z_OK)
! 2199: {
! 2200: ctf_dprintf ("zlib deflate err: %s\n", zError (rc));
! 2201: ctf_set_errno (fp, ECTF_COMPRESS);
! 2202: free (buf);
! 2203: return NULL;
! 2204: }
! 2205: *size += compress_len;
! 2206: }
! 2207: return buf;
! 2208: }
! 2209:
! 2210: /* Write the uncompressed CTF data stream to the specified file descriptor. */
! 2211: int
! 2212: ctf_write (ctf_file_t *fp, int fd)
! 2213: {
! 2214: const unsigned char *buf;
! 2215: ssize_t resid;
! 2216: ssize_t len;
! 2217:
! 2218: if (ctf_serialize (fp) < 0)
! 2219: return -1; /* errno is set for us. */
! 2220:
! 2221: resid = sizeof (ctf_header_t);
! 2222: buf = (unsigned char *) fp->ctf_header;
! 2223: while (resid != 0)
! 2224: {
! 2225: if ((len = write (fd, buf, resid)) <= 0)
! 2226: return (ctf_set_errno (fp, errno));
! 2227: resid -= len;
! 2228: buf += len;
! 2229: }
! 2230:
! 2231: resid = fp->ctf_size;
! 2232: buf = fp->ctf_buf;
! 2233: while (resid != 0)
! 2234: {
! 2235: if ((len = write (fd, buf, resid)) <= 0)
! 2236: return (ctf_set_errno (fp, errno));
! 2237: resid -= len;
! 2238: buf += len;
! 2239: }
! 2240:
! 2241: return 0;
! 2242: }
CVSweb <webmaster@jp.NetBSD.org>