14b169a6bSchristos /* CTF dict creation. 2*12989c96Schristos Copyright (C) 2019-2024 Free Software Foundation, Inc. 34b169a6bSchristos 44b169a6bSchristos This file is part of libctf. 54b169a6bSchristos 64b169a6bSchristos libctf is free software; you can redistribute it and/or modify it under 74b169a6bSchristos the terms of the GNU General Public License as published by the Free 84b169a6bSchristos Software Foundation; either version 3, or (at your option) any later 94b169a6bSchristos version. 104b169a6bSchristos 114b169a6bSchristos This program is distributed in the hope that it will be useful, but 124b169a6bSchristos WITHOUT ANY WARRANTY; without even the implied warranty of 134b169a6bSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 144b169a6bSchristos See the GNU General Public License for more details. 154b169a6bSchristos 164b169a6bSchristos You should have received a copy of the GNU General Public License 174b169a6bSchristos along with this program; see the file COPYING. If not see 184b169a6bSchristos <http://www.gnu.org/licenses/>. */ 194b169a6bSchristos 204b169a6bSchristos #include <ctf-impl.h> 214b169a6bSchristos #include <assert.h> 224b169a6bSchristos #include <string.h> 234b169a6bSchristos #include <unistd.h> 244b169a6bSchristos #include <zlib.h> 254b169a6bSchristos 264b169a6bSchristos #include <elf.h> 274b169a6bSchristos #include "elf-bfd.h" 284b169a6bSchristos 294b169a6bSchristos /* Symtypetab sections. */ 304b169a6bSchristos 314b169a6bSchristos /* Symtypetab emission flags. */ 324b169a6bSchristos 334b169a6bSchristos #define CTF_SYMTYPETAB_EMIT_FUNCTION 0x1 344b169a6bSchristos #define CTF_SYMTYPETAB_EMIT_PAD 0x2 354b169a6bSchristos #define CTF_SYMTYPETAB_FORCE_INDEXED 0x4 364b169a6bSchristos 374b169a6bSchristos /* Properties of symtypetab emission, shared by symtypetab section 384b169a6bSchristos sizing and symtypetab emission itself. */ 394b169a6bSchristos 404b169a6bSchristos typedef struct emit_symtypetab_state 414b169a6bSchristos { 424b169a6bSchristos /* True if linker-reported symbols are being filtered out. symfp is set if 434b169a6bSchristos this is true: otherwise, indexing is forced and the symflags indicate as 444b169a6bSchristos much. */ 454b169a6bSchristos int filter_syms; 464b169a6bSchristos 474b169a6bSchristos /* True if symbols are being sorted. */ 484b169a6bSchristos int sort_syms; 494b169a6bSchristos 504b169a6bSchristos /* Flags for symtypetab emission. */ 514b169a6bSchristos int symflags; 524b169a6bSchristos 534b169a6bSchristos /* The dict to which the linker has reported symbols. */ 544b169a6bSchristos ctf_dict_t *symfp; 554b169a6bSchristos 564b169a6bSchristos /* The maximum number of objects seen. */ 574b169a6bSchristos size_t maxobjt; 584b169a6bSchristos 594b169a6bSchristos /* The maximum number of func info entris seen. */ 604b169a6bSchristos size_t maxfunc; 614b169a6bSchristos } emit_symtypetab_state_t; 624b169a6bSchristos 634b169a6bSchristos /* Determine if a symbol is "skippable" and should never appear in the 644b169a6bSchristos symtypetab sections. */ 654b169a6bSchristos 664b169a6bSchristos int 674b169a6bSchristos ctf_symtab_skippable (ctf_link_sym_t *sym) 684b169a6bSchristos { 694b169a6bSchristos /* Never skip symbols whose name is not yet known. */ 704b169a6bSchristos if (sym->st_nameidx_set) 714b169a6bSchristos return 0; 724b169a6bSchristos 734b169a6bSchristos return (sym->st_name == NULL || sym->st_name[0] == 0 744b169a6bSchristos || sym->st_shndx == SHN_UNDEF 754b169a6bSchristos || strcmp (sym->st_name, "_START_") == 0 764b169a6bSchristos || strcmp (sym->st_name, "_END_") == 0 774b169a6bSchristos || (sym->st_type == STT_OBJECT && sym->st_shndx == SHN_EXTABS 784b169a6bSchristos && sym->st_value == 0)); 794b169a6bSchristos } 804b169a6bSchristos 814b169a6bSchristos /* Get the number of symbols in a symbol hash, the count of symbols, the maximum 824b169a6bSchristos seen, the eventual size, without any padding elements, of the func/data and 834b169a6bSchristos (if generated) index sections, and the size of accumulated padding elements. 844b169a6bSchristos The linker-reported set of symbols is found in SYMFP: it may be NULL if 854b169a6bSchristos symbol filtering is not desired, in which case CTF_SYMTYPETAB_FORCE_INDEXED 864b169a6bSchristos will always be set in the flags. 874b169a6bSchristos 884b169a6bSchristos Also figure out if any symbols need to be moved to the variable section, and 894b169a6bSchristos add them (if not already present). */ 904b169a6bSchristos 914b169a6bSchristos _libctf_nonnull_ ((1,3,4,5,6,7,8)) 924b169a6bSchristos static int 934b169a6bSchristos symtypetab_density (ctf_dict_t *fp, ctf_dict_t *symfp, ctf_dynhash_t *symhash, 944b169a6bSchristos size_t *count, size_t *max, size_t *unpadsize, 954b169a6bSchristos size_t *padsize, size_t *idxsize, int flags) 964b169a6bSchristos { 974b169a6bSchristos ctf_next_t *i = NULL; 984b169a6bSchristos const void *name; 994b169a6bSchristos const void *ctf_sym; 1004b169a6bSchristos ctf_dynhash_t *linker_known = NULL; 1014b169a6bSchristos int err; 1024b169a6bSchristos int beyond_max = 0; 1034b169a6bSchristos 1044b169a6bSchristos *count = 0; 1054b169a6bSchristos *max = 0; 1064b169a6bSchristos *unpadsize = 0; 1074b169a6bSchristos *idxsize = 0; 1084b169a6bSchristos *padsize = 0; 1094b169a6bSchristos 1104b169a6bSchristos if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED)) 1114b169a6bSchristos { 1124b169a6bSchristos /* Make a dynhash citing only symbols reported by the linker of the 1134b169a6bSchristos appropriate type, then traverse all potential-symbols we know the types 1144b169a6bSchristos of, removing them from linker_known as we go. Once this is done, the 1154b169a6bSchristos only symbols remaining in linker_known are symbols we don't know the 1164b169a6bSchristos types of: we must emit pads for those symbols that are below the 1174b169a6bSchristos maximum symbol we will emit (any beyond that are simply skipped). 1184b169a6bSchristos 1194b169a6bSchristos If there are none, this symtypetab will be empty: just report that. */ 1204b169a6bSchristos 1214b169a6bSchristos if (!symfp->ctf_dynsyms) 1224b169a6bSchristos return 0; 1234b169a6bSchristos 1244b169a6bSchristos if ((linker_known = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string, 1254b169a6bSchristos NULL, NULL)) == NULL) 1264b169a6bSchristos return (ctf_set_errno (fp, ENOMEM)); 1274b169a6bSchristos 1284b169a6bSchristos while ((err = ctf_dynhash_cnext (symfp->ctf_dynsyms, &i, 1294b169a6bSchristos &name, &ctf_sym)) == 0) 1304b169a6bSchristos { 1314b169a6bSchristos ctf_link_sym_t *sym = (ctf_link_sym_t *) ctf_sym; 1324b169a6bSchristos 1334b169a6bSchristos if (((flags & CTF_SYMTYPETAB_EMIT_FUNCTION) 1344b169a6bSchristos && sym->st_type != STT_FUNC) 1354b169a6bSchristos || (!(flags & CTF_SYMTYPETAB_EMIT_FUNCTION) 1364b169a6bSchristos && sym->st_type != STT_OBJECT)) 1374b169a6bSchristos continue; 1384b169a6bSchristos 1394b169a6bSchristos if (ctf_symtab_skippable (sym)) 1404b169a6bSchristos continue; 1414b169a6bSchristos 1424b169a6bSchristos /* This should only be true briefly before all the names are 1434b169a6bSchristos finalized, long before we get this far. */ 1444b169a6bSchristos if (!ctf_assert (fp, !sym->st_nameidx_set)) 1454b169a6bSchristos return -1; /* errno is set for us. */ 1464b169a6bSchristos 1474b169a6bSchristos if (ctf_dynhash_cinsert (linker_known, name, ctf_sym) < 0) 1484b169a6bSchristos { 1494b169a6bSchristos ctf_dynhash_destroy (linker_known); 1504b169a6bSchristos return (ctf_set_errno (fp, ENOMEM)); 1514b169a6bSchristos } 1524b169a6bSchristos } 1534b169a6bSchristos if (err != ECTF_NEXT_END) 1544b169a6bSchristos { 1554b169a6bSchristos ctf_err_warn (fp, 0, err, _("iterating over linker-known symbols during " 1564b169a6bSchristos "serialization")); 1574b169a6bSchristos ctf_dynhash_destroy (linker_known); 1584b169a6bSchristos return (ctf_set_errno (fp, err)); 1594b169a6bSchristos } 1604b169a6bSchristos } 1614b169a6bSchristos 1624b169a6bSchristos while ((err = ctf_dynhash_cnext (symhash, &i, &name, NULL)) == 0) 1634b169a6bSchristos { 1644b169a6bSchristos ctf_link_sym_t *sym; 1654b169a6bSchristos 1664b169a6bSchristos if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED)) 1674b169a6bSchristos { 1684b169a6bSchristos /* Linker did not report symbol in symtab. Remove it from the 1694b169a6bSchristos set of known data symbols and continue. */ 1704b169a6bSchristos if ((sym = ctf_dynhash_lookup (symfp->ctf_dynsyms, name)) == NULL) 1714b169a6bSchristos { 1724b169a6bSchristos ctf_dynhash_remove (symhash, name); 1734b169a6bSchristos continue; 1744b169a6bSchristos } 1754b169a6bSchristos 1764b169a6bSchristos /* We don't remove skippable symbols from the symhash because we don't 1774b169a6bSchristos want them to be migrated into variables. */ 1784b169a6bSchristos if (ctf_symtab_skippable (sym)) 1794b169a6bSchristos continue; 1804b169a6bSchristos 1814b169a6bSchristos if ((flags & CTF_SYMTYPETAB_EMIT_FUNCTION) 1824b169a6bSchristos && sym->st_type != STT_FUNC) 1834b169a6bSchristos { 1844b169a6bSchristos ctf_err_warn (fp, 1, 0, _("symbol %s (%x) added to CTF as a " 1854b169a6bSchristos "function but is of type %x. " 1864b169a6bSchristos "The symbol type lookup tables " 1874b169a6bSchristos "are probably corrupted"), 1884b169a6bSchristos sym->st_name, sym->st_symidx, sym->st_type); 1894b169a6bSchristos ctf_dynhash_remove (symhash, name); 1904b169a6bSchristos continue; 1914b169a6bSchristos } 1924b169a6bSchristos else if (!(flags & CTF_SYMTYPETAB_EMIT_FUNCTION) 1934b169a6bSchristos && sym->st_type != STT_OBJECT) 1944b169a6bSchristos { 1954b169a6bSchristos ctf_err_warn (fp, 1, 0, _("symbol %s (%x) added to CTF as a " 1964b169a6bSchristos "data object but is of type %x. " 1974b169a6bSchristos "The symbol type lookup tables " 1984b169a6bSchristos "are probably corrupted"), 1994b169a6bSchristos sym->st_name, sym->st_symidx, sym->st_type); 2004b169a6bSchristos ctf_dynhash_remove (symhash, name); 2014b169a6bSchristos continue; 2024b169a6bSchristos } 2034b169a6bSchristos 2044b169a6bSchristos ctf_dynhash_remove (linker_known, name); 2054b169a6bSchristos 2064b169a6bSchristos if (*max < sym->st_symidx) 2074b169a6bSchristos *max = sym->st_symidx; 2084b169a6bSchristos } 2094b169a6bSchristos else 2104b169a6bSchristos (*max)++; 211*12989c96Schristos 212*12989c96Schristos *unpadsize += sizeof (uint32_t); 213*12989c96Schristos (*count)++; 2144b169a6bSchristos } 2154b169a6bSchristos if (err != ECTF_NEXT_END) 2164b169a6bSchristos { 2174b169a6bSchristos ctf_err_warn (fp, 0, err, _("iterating over CTF symtypetab during " 2184b169a6bSchristos "serialization")); 2194b169a6bSchristos ctf_dynhash_destroy (linker_known); 2204b169a6bSchristos return (ctf_set_errno (fp, err)); 2214b169a6bSchristos } 2224b169a6bSchristos 2234b169a6bSchristos if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED)) 2244b169a6bSchristos { 2254b169a6bSchristos while ((err = ctf_dynhash_cnext (linker_known, &i, NULL, &ctf_sym)) == 0) 2264b169a6bSchristos { 2274b169a6bSchristos ctf_link_sym_t *sym = (ctf_link_sym_t *) ctf_sym; 2284b169a6bSchristos 2294b169a6bSchristos if (sym->st_symidx > *max) 2304b169a6bSchristos beyond_max++; 2314b169a6bSchristos } 2324b169a6bSchristos if (err != ECTF_NEXT_END) 2334b169a6bSchristos { 2344b169a6bSchristos ctf_err_warn (fp, 0, err, _("iterating over linker-known symbols " 2354b169a6bSchristos "during CTF serialization")); 2364b169a6bSchristos ctf_dynhash_destroy (linker_known); 2374b169a6bSchristos return (ctf_set_errno (fp, err)); 2384b169a6bSchristos } 2394b169a6bSchristos } 2404b169a6bSchristos 2414b169a6bSchristos *idxsize = *count * sizeof (uint32_t); 2424b169a6bSchristos if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED)) 2434b169a6bSchristos *padsize = (ctf_dynhash_elements (linker_known) - beyond_max) * sizeof (uint32_t); 2444b169a6bSchristos 2454b169a6bSchristos ctf_dynhash_destroy (linker_known); 2464b169a6bSchristos return 0; 2474b169a6bSchristos } 2484b169a6bSchristos 2494b169a6bSchristos /* Emit an objt or func symtypetab into DP in a particular order defined by an 2504b169a6bSchristos array of ctf_link_sym_t or symbol names passed in. The index has NIDX 2514b169a6bSchristos elements in it: unindexed output would terminate at symbol OUTMAX and is in 2524b169a6bSchristos any case no larger than SIZE bytes. Some index elements are expected to be 2534b169a6bSchristos skipped: see symtypetab_density. The linker-reported set of symbols (if any) 2544b169a6bSchristos is found in SYMFP. */ 2554b169a6bSchristos static int 2564b169a6bSchristos emit_symtypetab (ctf_dict_t *fp, ctf_dict_t *symfp, uint32_t *dp, 2574b169a6bSchristos ctf_link_sym_t **idx, const char **nameidx, uint32_t nidx, 2584b169a6bSchristos uint32_t outmax, int size, int flags) 2594b169a6bSchristos { 2604b169a6bSchristos uint32_t i; 2614b169a6bSchristos uint32_t *dpp = dp; 2624b169a6bSchristos ctf_dynhash_t *symhash; 2634b169a6bSchristos 2644b169a6bSchristos ctf_dprintf ("Emitting table of size %i, outmax %u, %u symtypetab entries, " 2654b169a6bSchristos "flags %i\n", size, outmax, nidx, flags); 2664b169a6bSchristos 2674b169a6bSchristos /* Empty table? Nothing to do. */ 2684b169a6bSchristos if (size == 0) 2694b169a6bSchristos return 0; 2704b169a6bSchristos 2714b169a6bSchristos if (flags & CTF_SYMTYPETAB_EMIT_FUNCTION) 2724b169a6bSchristos symhash = fp->ctf_funchash; 2734b169a6bSchristos else 2744b169a6bSchristos symhash = fp->ctf_objthash; 2754b169a6bSchristos 2764b169a6bSchristos for (i = 0; i < nidx; i++) 2774b169a6bSchristos { 2784b169a6bSchristos const char *sym_name; 2794b169a6bSchristos void *type; 2804b169a6bSchristos 2814b169a6bSchristos /* If we have a linker-reported set of symbols, we may be given that set 2824b169a6bSchristos to work from, or a set of symbol names. In both cases we want to look 2834b169a6bSchristos at the corresponding linker-reported symbol (if any). */ 2844b169a6bSchristos if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED)) 2854b169a6bSchristos { 2864b169a6bSchristos ctf_link_sym_t *this_link_sym; 2874b169a6bSchristos 2884b169a6bSchristos if (idx) 2894b169a6bSchristos this_link_sym = idx[i]; 2904b169a6bSchristos else 2914b169a6bSchristos this_link_sym = ctf_dynhash_lookup (symfp->ctf_dynsyms, nameidx[i]); 2924b169a6bSchristos 2934b169a6bSchristos /* Unreported symbol number. No pad, no nothing. */ 2944b169a6bSchristos if (!this_link_sym) 2954b169a6bSchristos continue; 2964b169a6bSchristos 2974b169a6bSchristos /* Symbol of the wrong type, or skippable? This symbol is not in this 2984b169a6bSchristos table. */ 2994b169a6bSchristos if (((flags & CTF_SYMTYPETAB_EMIT_FUNCTION) 3004b169a6bSchristos && this_link_sym->st_type != STT_FUNC) 3014b169a6bSchristos || (!(flags & CTF_SYMTYPETAB_EMIT_FUNCTION) 3024b169a6bSchristos && this_link_sym->st_type != STT_OBJECT)) 3034b169a6bSchristos continue; 3044b169a6bSchristos 3054b169a6bSchristos if (ctf_symtab_skippable (this_link_sym)) 3064b169a6bSchristos continue; 3074b169a6bSchristos 3084b169a6bSchristos sym_name = this_link_sym->st_name; 3094b169a6bSchristos 3104b169a6bSchristos /* Linker reports symbol of a different type to the symbol we actually 3114b169a6bSchristos added? Skip the symbol. No pad, since the symbol doesn't actually 3124b169a6bSchristos belong in this table at all. (Warned about in 3134b169a6bSchristos symtypetab_density.) */ 3144b169a6bSchristos if ((this_link_sym->st_type == STT_FUNC) 3154b169a6bSchristos && (ctf_dynhash_lookup (fp->ctf_objthash, sym_name))) 3164b169a6bSchristos continue; 3174b169a6bSchristos 3184b169a6bSchristos if ((this_link_sym->st_type == STT_OBJECT) 3194b169a6bSchristos && (ctf_dynhash_lookup (fp->ctf_funchash, sym_name))) 3204b169a6bSchristos continue; 3214b169a6bSchristos } 3224b169a6bSchristos else 3234b169a6bSchristos sym_name = nameidx[i]; 3244b169a6bSchristos 3254b169a6bSchristos /* Symbol in index but no type set? Silently skip and (optionally) 3264b169a6bSchristos pad. (In force-indexed mode, this is also where we track symbols of 3274b169a6bSchristos the wrong type for this round of insertion.) */ 3284b169a6bSchristos if ((type = ctf_dynhash_lookup (symhash, sym_name)) == NULL) 3294b169a6bSchristos { 3304b169a6bSchristos if (flags & CTF_SYMTYPETAB_EMIT_PAD) 3314b169a6bSchristos *dpp++ = 0; 3324b169a6bSchristos continue; 3334b169a6bSchristos } 3344b169a6bSchristos 3354b169a6bSchristos if (!ctf_assert (fp, (((char *) dpp) - (char *) dp) < size)) 3364b169a6bSchristos return -1; /* errno is set for us. */ 3374b169a6bSchristos 3384b169a6bSchristos *dpp++ = (ctf_id_t) (uintptr_t) type; 3394b169a6bSchristos 3404b169a6bSchristos /* When emitting unindexed output, all later symbols are pads: stop 3414b169a6bSchristos early. */ 3424b169a6bSchristos if ((flags & CTF_SYMTYPETAB_EMIT_PAD) && idx[i]->st_symidx == outmax) 3434b169a6bSchristos break; 3444b169a6bSchristos } 3454b169a6bSchristos 3464b169a6bSchristos return 0; 3474b169a6bSchristos } 3484b169a6bSchristos 3494b169a6bSchristos /* Emit an objt or func symtypetab index into DP in a paticular order defined by 3504b169a6bSchristos an array of symbol names passed in. Stop at NIDX. The linker-reported set 3514b169a6bSchristos of symbols (if any) is found in SYMFP. */ 3524b169a6bSchristos static int 3534b169a6bSchristos emit_symtypetab_index (ctf_dict_t *fp, ctf_dict_t *symfp, uint32_t *dp, 3544b169a6bSchristos const char **idx, uint32_t nidx, int size, int flags) 3554b169a6bSchristos { 3564b169a6bSchristos uint32_t i; 3574b169a6bSchristos uint32_t *dpp = dp; 3584b169a6bSchristos ctf_dynhash_t *symhash; 3594b169a6bSchristos 3604b169a6bSchristos ctf_dprintf ("Emitting index of size %i, %u entries reported by linker, " 3614b169a6bSchristos "flags %i\n", size, nidx, flags); 3624b169a6bSchristos 3634b169a6bSchristos /* Empty table? Nothing to do. */ 3644b169a6bSchristos if (size == 0) 3654b169a6bSchristos return 0; 3664b169a6bSchristos 3674b169a6bSchristos if (flags & CTF_SYMTYPETAB_EMIT_FUNCTION) 3684b169a6bSchristos symhash = fp->ctf_funchash; 3694b169a6bSchristos else 3704b169a6bSchristos symhash = fp->ctf_objthash; 3714b169a6bSchristos 3724b169a6bSchristos /* Indexes should always be unpadded. */ 3734b169a6bSchristos if (!ctf_assert (fp, !(flags & CTF_SYMTYPETAB_EMIT_PAD))) 3744b169a6bSchristos return -1; /* errno is set for us. */ 3754b169a6bSchristos 3764b169a6bSchristos for (i = 0; i < nidx; i++) 3774b169a6bSchristos { 3784b169a6bSchristos const char *sym_name; 3794b169a6bSchristos void *type; 3804b169a6bSchristos 3814b169a6bSchristos if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED)) 3824b169a6bSchristos { 3834b169a6bSchristos ctf_link_sym_t *this_link_sym; 3844b169a6bSchristos 3854b169a6bSchristos this_link_sym = ctf_dynhash_lookup (symfp->ctf_dynsyms, idx[i]); 3864b169a6bSchristos 3874b169a6bSchristos /* This is an index: unreported symbols should never appear in it. */ 3884b169a6bSchristos if (!ctf_assert (fp, this_link_sym != NULL)) 3894b169a6bSchristos return -1; /* errno is set for us. */ 3904b169a6bSchristos 3914b169a6bSchristos /* Symbol of the wrong type, or skippable? This symbol is not in this 3924b169a6bSchristos table. */ 3934b169a6bSchristos if (((flags & CTF_SYMTYPETAB_EMIT_FUNCTION) 3944b169a6bSchristos && this_link_sym->st_type != STT_FUNC) 3954b169a6bSchristos || (!(flags & CTF_SYMTYPETAB_EMIT_FUNCTION) 3964b169a6bSchristos && this_link_sym->st_type != STT_OBJECT)) 3974b169a6bSchristos continue; 3984b169a6bSchristos 3994b169a6bSchristos if (ctf_symtab_skippable (this_link_sym)) 4004b169a6bSchristos continue; 4014b169a6bSchristos 4024b169a6bSchristos sym_name = this_link_sym->st_name; 4034b169a6bSchristos 4044b169a6bSchristos /* Linker reports symbol of a different type to the symbol we actually 4054b169a6bSchristos added? Skip the symbol. */ 4064b169a6bSchristos if ((this_link_sym->st_type == STT_FUNC) 4074b169a6bSchristos && (ctf_dynhash_lookup (fp->ctf_objthash, sym_name))) 4084b169a6bSchristos continue; 4094b169a6bSchristos 4104b169a6bSchristos if ((this_link_sym->st_type == STT_OBJECT) 4114b169a6bSchristos && (ctf_dynhash_lookup (fp->ctf_funchash, sym_name))) 4124b169a6bSchristos continue; 4134b169a6bSchristos } 4144b169a6bSchristos else 4154b169a6bSchristos sym_name = idx[i]; 4164b169a6bSchristos 4174b169a6bSchristos /* Symbol in index and reported by linker, but no type set? Silently skip 4184b169a6bSchristos and (optionally) pad. (In force-indexed mode, this is also where we 4194b169a6bSchristos track symbols of the wrong type for this round of insertion.) */ 4204b169a6bSchristos if ((type = ctf_dynhash_lookup (symhash, sym_name)) == NULL) 4214b169a6bSchristos continue; 4224b169a6bSchristos 4234b169a6bSchristos ctf_str_add_ref (fp, sym_name, dpp++); 4244b169a6bSchristos 4254b169a6bSchristos if (!ctf_assert (fp, (((char *) dpp) - (char *) dp) <= size)) 4264b169a6bSchristos return -1; /* errno is set for us. */ 4274b169a6bSchristos } 4284b169a6bSchristos 4294b169a6bSchristos return 0; 4304b169a6bSchristos } 4314b169a6bSchristos 4324b169a6bSchristos /* Delete symbols that have been assigned names from the variable section. Must 4334b169a6bSchristos be called from within ctf_serialize, because that is the only place you can 4344b169a6bSchristos safely delete variables without messing up ctf_rollback. */ 4354b169a6bSchristos 4364b169a6bSchristos static int 4374b169a6bSchristos symtypetab_delete_nonstatics (ctf_dict_t *fp, ctf_dict_t *symfp) 4384b169a6bSchristos { 4394b169a6bSchristos ctf_dvdef_t *dvd, *nvd; 4404b169a6bSchristos ctf_id_t type; 4414b169a6bSchristos 4424b169a6bSchristos for (dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; dvd = nvd) 4434b169a6bSchristos { 4444b169a6bSchristos nvd = ctf_list_next (dvd); 4454b169a6bSchristos 4464b169a6bSchristos if ((((type = (ctf_id_t) (uintptr_t) 4474b169a6bSchristos ctf_dynhash_lookup (fp->ctf_objthash, dvd->dvd_name)) > 0) 4484b169a6bSchristos || (type = (ctf_id_t) (uintptr_t) 4494b169a6bSchristos ctf_dynhash_lookup (fp->ctf_funchash, dvd->dvd_name)) > 0) 4504b169a6bSchristos && ctf_dynhash_lookup (symfp->ctf_dynsyms, dvd->dvd_name) != NULL 4514b169a6bSchristos && type == dvd->dvd_type) 4524b169a6bSchristos ctf_dvd_delete (fp, dvd); 4534b169a6bSchristos } 4544b169a6bSchristos 4554b169a6bSchristos return 0; 4564b169a6bSchristos } 4574b169a6bSchristos 4584b169a6bSchristos /* Figure out the sizes of the symtypetab sections, their indexed state, 4594b169a6bSchristos etc. */ 4604b169a6bSchristos static int 4614b169a6bSchristos ctf_symtypetab_sect_sizes (ctf_dict_t *fp, emit_symtypetab_state_t *s, 4624b169a6bSchristos ctf_header_t *hdr, size_t *objt_size, 4634b169a6bSchristos size_t *func_size, size_t *objtidx_size, 4644b169a6bSchristos size_t *funcidx_size) 4654b169a6bSchristos { 4664b169a6bSchristos size_t nfuncs, nobjts; 4674b169a6bSchristos size_t objt_unpadsize, func_unpadsize, objt_padsize, func_padsize; 4684b169a6bSchristos 4694b169a6bSchristos /* If doing a writeout as part of linking, and the link flags request it, 4704b169a6bSchristos filter out reported symbols from the variable section, and filter out all 4714b169a6bSchristos other symbols from the symtypetab sections. (If we are not linking, the 4724b169a6bSchristos symbols are sorted; if we are linking, don't bother sorting if we are not 473*12989c96Schristos filtering out reported symbols: this is almost certainly an ld -r and only 4744b169a6bSchristos the linker is likely to consume these symtypetabs again. The linker 475*12989c96Schristos doesn't care what order the symtypetab entries are in, since it only 4764b169a6bSchristos iterates over symbols and does not use the ctf_lookup_by_symbol* API.) */ 4774b169a6bSchristos 4784b169a6bSchristos s->sort_syms = 1; 4794b169a6bSchristos if (fp->ctf_flags & LCTF_LINKING) 4804b169a6bSchristos { 4814b169a6bSchristos s->filter_syms = !(fp->ctf_link_flags & CTF_LINK_NO_FILTER_REPORTED_SYMS); 4824b169a6bSchristos if (!s->filter_syms) 4834b169a6bSchristos s->sort_syms = 0; 4844b169a6bSchristos } 4854b169a6bSchristos 4864b169a6bSchristos /* Find the dict to which the linker has reported symbols, if any. */ 4874b169a6bSchristos 4884b169a6bSchristos if (s->filter_syms) 4894b169a6bSchristos { 4904b169a6bSchristos if (!fp->ctf_dynsyms && fp->ctf_parent && fp->ctf_parent->ctf_dynsyms) 4914b169a6bSchristos s->symfp = fp->ctf_parent; 4924b169a6bSchristos else 4934b169a6bSchristos s->symfp = fp; 4944b169a6bSchristos } 4954b169a6bSchristos 4964b169a6bSchristos /* If not filtering, keep all potential symbols in an unsorted, indexed 4974b169a6bSchristos dict. */ 4984b169a6bSchristos if (!s->filter_syms) 4994b169a6bSchristos s->symflags = CTF_SYMTYPETAB_FORCE_INDEXED; 5004b169a6bSchristos else 5014b169a6bSchristos hdr->cth_flags |= CTF_F_IDXSORTED; 5024b169a6bSchristos 5034b169a6bSchristos if (!ctf_assert (fp, (s->filter_syms && s->symfp) 5044b169a6bSchristos || (!s->filter_syms && !s->symfp 5054b169a6bSchristos && ((s->symflags & CTF_SYMTYPETAB_FORCE_INDEXED) != 0)))) 5064b169a6bSchristos return -1; 5074b169a6bSchristos 5084b169a6bSchristos /* Work out the sizes of the object and function sections, and work out the 5094b169a6bSchristos number of pad (unassigned) symbols in each, and the overall size of the 5104b169a6bSchristos sections. */ 5114b169a6bSchristos 5124b169a6bSchristos if (symtypetab_density (fp, s->symfp, fp->ctf_objthash, &nobjts, &s->maxobjt, 5134b169a6bSchristos &objt_unpadsize, &objt_padsize, objtidx_size, 5144b169a6bSchristos s->symflags) < 0) 5154b169a6bSchristos return -1; /* errno is set for us. */ 5164b169a6bSchristos 5174b169a6bSchristos ctf_dprintf ("Object symtypetab: %i objects, max %i, unpadded size %i, " 5184b169a6bSchristos "%i bytes of pads, index size %i\n", (int) nobjts, 5194b169a6bSchristos (int) s->maxobjt, (int) objt_unpadsize, (int) objt_padsize, 5204b169a6bSchristos (int) *objtidx_size); 5214b169a6bSchristos 5224b169a6bSchristos if (symtypetab_density (fp, s->symfp, fp->ctf_funchash, &nfuncs, &s->maxfunc, 5234b169a6bSchristos &func_unpadsize, &func_padsize, funcidx_size, 5244b169a6bSchristos s->symflags | CTF_SYMTYPETAB_EMIT_FUNCTION) < 0) 5254b169a6bSchristos return -1; /* errno is set for us. */ 5264b169a6bSchristos 5274b169a6bSchristos ctf_dprintf ("Function symtypetab: %i functions, max %i, unpadded size %i, " 5284b169a6bSchristos "%i bytes of pads, index size %i\n", (int) nfuncs, 5294b169a6bSchristos (int) s->maxfunc, (int) func_unpadsize, (int) func_padsize, 5304b169a6bSchristos (int) *funcidx_size); 5314b169a6bSchristos 5324b169a6bSchristos /* It is worth indexing each section if it would save space to do so, due to 5334b169a6bSchristos reducing the number of pads sufficiently. A pad is the same size as a 5344b169a6bSchristos single index entry: but index sections compress relatively poorly compared 5354b169a6bSchristos to constant pads, so it takes a lot of contiguous padding to equal one 5364b169a6bSchristos index section entry. It would be nice to be able to *verify* whether we 5374b169a6bSchristos would save space after compression rather than guessing, but this seems 5384b169a6bSchristos difficult, since it would require complete reserialization. Regardless, if 5394b169a6bSchristos the linker has not reported any symbols (e.g. if this is not a final link 5404b169a6bSchristos but just an ld -r), we must emit things in indexed fashion just as the 5414b169a6bSchristos compiler does. */ 5424b169a6bSchristos 5434b169a6bSchristos *objt_size = objt_unpadsize; 5444b169a6bSchristos if (!(s->symflags & CTF_SYMTYPETAB_FORCE_INDEXED) 5454b169a6bSchristos && ((objt_padsize + objt_unpadsize) * CTF_INDEX_PAD_THRESHOLD 5464b169a6bSchristos > objt_padsize)) 5474b169a6bSchristos { 5484b169a6bSchristos *objt_size += objt_padsize; 5494b169a6bSchristos *objtidx_size = 0; 5504b169a6bSchristos } 5514b169a6bSchristos 5524b169a6bSchristos *func_size = func_unpadsize; 5534b169a6bSchristos if (!(s->symflags & CTF_SYMTYPETAB_FORCE_INDEXED) 5544b169a6bSchristos && ((func_padsize + func_unpadsize) * CTF_INDEX_PAD_THRESHOLD 5554b169a6bSchristos > func_padsize)) 5564b169a6bSchristos { 5574b169a6bSchristos *func_size += func_padsize; 5584b169a6bSchristos *funcidx_size = 0; 5594b169a6bSchristos } 5604b169a6bSchristos 5614b169a6bSchristos /* If we are filtering symbols out, those symbols that the linker has not 5624b169a6bSchristos reported have now been removed from the ctf_objthash and ctf_funchash. 5634b169a6bSchristos Delete entries from the variable section that duplicate newly-added 5644b169a6bSchristos symbols. There's no need to migrate new ones in: we do that (if necessary) 5654b169a6bSchristos in ctf_link_deduplicating_variables. */ 5664b169a6bSchristos 5674b169a6bSchristos if (s->filter_syms && s->symfp->ctf_dynsyms && 5684b169a6bSchristos symtypetab_delete_nonstatics (fp, s->symfp) < 0) 5694b169a6bSchristos return -1; 5704b169a6bSchristos 5714b169a6bSchristos return 0; 5724b169a6bSchristos } 5734b169a6bSchristos 5744b169a6bSchristos static int 5754b169a6bSchristos ctf_emit_symtypetab_sects (ctf_dict_t *fp, emit_symtypetab_state_t *s, 5764b169a6bSchristos unsigned char **tptr, size_t objt_size, 5774b169a6bSchristos size_t func_size, size_t objtidx_size, 5784b169a6bSchristos size_t funcidx_size) 5794b169a6bSchristos { 5804b169a6bSchristos unsigned char *t = *tptr; 5814b169a6bSchristos size_t nsymtypes = 0; 5824b169a6bSchristos const char **sym_name_order = NULL; 5834b169a6bSchristos int err; 5844b169a6bSchristos 5854b169a6bSchristos /* Sort the linker's symbols into name order if need be. */ 5864b169a6bSchristos 5874b169a6bSchristos if ((objtidx_size != 0) || (funcidx_size != 0)) 5884b169a6bSchristos { 5894b169a6bSchristos ctf_next_t *i = NULL; 5904b169a6bSchristos void *symname; 5914b169a6bSchristos const char **walk; 5924b169a6bSchristos 5934b169a6bSchristos if (s->filter_syms) 5944b169a6bSchristos { 5954b169a6bSchristos if (s->symfp->ctf_dynsyms) 5964b169a6bSchristos nsymtypes = ctf_dynhash_elements (s->symfp->ctf_dynsyms); 5974b169a6bSchristos else 5984b169a6bSchristos nsymtypes = 0; 5994b169a6bSchristos } 6004b169a6bSchristos else 6014b169a6bSchristos nsymtypes = ctf_dynhash_elements (fp->ctf_objthash) 6024b169a6bSchristos + ctf_dynhash_elements (fp->ctf_funchash); 6034b169a6bSchristos 6044b169a6bSchristos if ((sym_name_order = calloc (nsymtypes, sizeof (const char *))) == NULL) 6054b169a6bSchristos goto oom; 6064b169a6bSchristos 6074b169a6bSchristos walk = sym_name_order; 6084b169a6bSchristos 6094b169a6bSchristos if (s->filter_syms) 6104b169a6bSchristos { 6114b169a6bSchristos if (s->symfp->ctf_dynsyms) 6124b169a6bSchristos { 6134b169a6bSchristos while ((err = ctf_dynhash_next_sorted (s->symfp->ctf_dynsyms, &i, 6144b169a6bSchristos &symname, NULL, 6154b169a6bSchristos ctf_dynhash_sort_by_name, 6164b169a6bSchristos NULL)) == 0) 6174b169a6bSchristos *walk++ = (const char *) symname; 6184b169a6bSchristos if (err != ECTF_NEXT_END) 6194b169a6bSchristos goto symerr; 6204b169a6bSchristos } 6214b169a6bSchristos } 6224b169a6bSchristos else 6234b169a6bSchristos { 6244b169a6bSchristos ctf_hash_sort_f sort_fun = NULL; 6254b169a6bSchristos 6264b169a6bSchristos /* Since we partition the set of symbols back into objt and func, 6274b169a6bSchristos we can sort the two independently without harm. */ 6284b169a6bSchristos if (s->sort_syms) 6294b169a6bSchristos sort_fun = ctf_dynhash_sort_by_name; 6304b169a6bSchristos 6314b169a6bSchristos while ((err = ctf_dynhash_next_sorted (fp->ctf_objthash, &i, &symname, 6324b169a6bSchristos NULL, sort_fun, NULL)) == 0) 6334b169a6bSchristos *walk++ = (const char *) symname; 6344b169a6bSchristos if (err != ECTF_NEXT_END) 6354b169a6bSchristos goto symerr; 6364b169a6bSchristos 6374b169a6bSchristos while ((err = ctf_dynhash_next_sorted (fp->ctf_funchash, &i, &symname, 6384b169a6bSchristos NULL, sort_fun, NULL)) == 0) 6394b169a6bSchristos *walk++ = (const char *) symname; 6404b169a6bSchristos if (err != ECTF_NEXT_END) 6414b169a6bSchristos goto symerr; 6424b169a6bSchristos } 6434b169a6bSchristos } 6444b169a6bSchristos 6454b169a6bSchristos /* Emit the object and function sections, and if necessary their indexes. 6464b169a6bSchristos Emission is done in symtab order if there is no index, and in index 6474b169a6bSchristos (name) order otherwise. */ 6484b169a6bSchristos 6494b169a6bSchristos if ((objtidx_size == 0) && s->symfp && s->symfp->ctf_dynsymidx) 6504b169a6bSchristos { 6514b169a6bSchristos ctf_dprintf ("Emitting unindexed objt symtypetab\n"); 6524b169a6bSchristos if (emit_symtypetab (fp, s->symfp, (uint32_t *) t, 6534b169a6bSchristos s->symfp->ctf_dynsymidx, NULL, 6544b169a6bSchristos s->symfp->ctf_dynsymmax + 1, s->maxobjt, 6554b169a6bSchristos objt_size, s->symflags | CTF_SYMTYPETAB_EMIT_PAD) < 0) 6564b169a6bSchristos goto err; /* errno is set for us. */ 6574b169a6bSchristos } 6584b169a6bSchristos else 6594b169a6bSchristos { 6604b169a6bSchristos ctf_dprintf ("Emitting indexed objt symtypetab\n"); 6614b169a6bSchristos if (emit_symtypetab (fp, s->symfp, (uint32_t *) t, NULL, 6624b169a6bSchristos sym_name_order, nsymtypes, s->maxobjt, 6634b169a6bSchristos objt_size, s->symflags) < 0) 6644b169a6bSchristos goto err; /* errno is set for us. */ 6654b169a6bSchristos } 6664b169a6bSchristos 6674b169a6bSchristos t += objt_size; 6684b169a6bSchristos 6694b169a6bSchristos if ((funcidx_size == 0) && s->symfp && s->symfp->ctf_dynsymidx) 6704b169a6bSchristos { 6714b169a6bSchristos ctf_dprintf ("Emitting unindexed func symtypetab\n"); 6724b169a6bSchristos if (emit_symtypetab (fp, s->symfp, (uint32_t *) t, 6734b169a6bSchristos s->symfp->ctf_dynsymidx, NULL, 6744b169a6bSchristos s->symfp->ctf_dynsymmax + 1, s->maxfunc, 6754b169a6bSchristos func_size, s->symflags | CTF_SYMTYPETAB_EMIT_FUNCTION 6764b169a6bSchristos | CTF_SYMTYPETAB_EMIT_PAD) < 0) 6774b169a6bSchristos goto err; /* errno is set for us. */ 6784b169a6bSchristos } 6794b169a6bSchristos else 6804b169a6bSchristos { 6814b169a6bSchristos ctf_dprintf ("Emitting indexed func symtypetab\n"); 6824b169a6bSchristos if (emit_symtypetab (fp, s->symfp, (uint32_t *) t, NULL, sym_name_order, 6834b169a6bSchristos nsymtypes, s->maxfunc, func_size, 6844b169a6bSchristos s->symflags | CTF_SYMTYPETAB_EMIT_FUNCTION) < 0) 6854b169a6bSchristos goto err; /* errno is set for us. */ 6864b169a6bSchristos } 6874b169a6bSchristos 6884b169a6bSchristos t += func_size; 6894b169a6bSchristos 6904b169a6bSchristos if (objtidx_size > 0) 6914b169a6bSchristos if (emit_symtypetab_index (fp, s->symfp, (uint32_t *) t, sym_name_order, 6924b169a6bSchristos nsymtypes, objtidx_size, s->symflags) < 0) 6934b169a6bSchristos goto err; 6944b169a6bSchristos 6954b169a6bSchristos t += objtidx_size; 6964b169a6bSchristos 6974b169a6bSchristos if (funcidx_size > 0) 6984b169a6bSchristos if (emit_symtypetab_index (fp, s->symfp, (uint32_t *) t, sym_name_order, 6994b169a6bSchristos nsymtypes, funcidx_size, 7004b169a6bSchristos s->symflags | CTF_SYMTYPETAB_EMIT_FUNCTION) < 0) 7014b169a6bSchristos goto err; 7024b169a6bSchristos 7034b169a6bSchristos t += funcidx_size; 7044b169a6bSchristos free (sym_name_order); 7054b169a6bSchristos *tptr = t; 7064b169a6bSchristos 7074b169a6bSchristos return 0; 7084b169a6bSchristos 7094b169a6bSchristos oom: 7104b169a6bSchristos ctf_set_errno (fp, EAGAIN); 7114b169a6bSchristos goto err; 7124b169a6bSchristos symerr: 7134b169a6bSchristos ctf_err_warn (fp, 0, err, _("error serializing symtypetabs")); 7144b169a6bSchristos err: 7154b169a6bSchristos free (sym_name_order); 7164b169a6bSchristos return -1; 7174b169a6bSchristos } 7184b169a6bSchristos 7194b169a6bSchristos /* Type section. */ 7204b169a6bSchristos 721*12989c96Schristos /* Iterate through the static types and the dynamic type definition list and 722*12989c96Schristos compute the size of the CTF type section. */ 7234b169a6bSchristos 7244b169a6bSchristos static size_t 7254b169a6bSchristos ctf_type_sect_size (ctf_dict_t *fp) 7264b169a6bSchristos { 7274b169a6bSchristos ctf_dtdef_t *dtd; 7284b169a6bSchristos size_t type_size; 7294b169a6bSchristos 7304b169a6bSchristos for (type_size = 0, dtd = ctf_list_next (&fp->ctf_dtdefs); 7314b169a6bSchristos dtd != NULL; dtd = ctf_list_next (dtd)) 7324b169a6bSchristos { 7334b169a6bSchristos uint32_t kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info); 7344b169a6bSchristos uint32_t vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info); 7354b169a6bSchristos size_t type_ctt_size = dtd->dtd_data.ctt_size; 7364b169a6bSchristos 7374b169a6bSchristos /* Shrink ctf_type_t-using types from a ctf_type_t to a ctf_stype_t 7384b169a6bSchristos if possible. */ 7394b169a6bSchristos 7404b169a6bSchristos if (kind == CTF_K_STRUCT || kind == CTF_K_UNION) 7414b169a6bSchristos { 7424b169a6bSchristos size_t lsize = CTF_TYPE_LSIZE (&dtd->dtd_data); 7434b169a6bSchristos 7444b169a6bSchristos if (lsize <= CTF_MAX_SIZE) 7454b169a6bSchristos type_ctt_size = lsize; 7464b169a6bSchristos } 7474b169a6bSchristos 7484b169a6bSchristos if (type_ctt_size != CTF_LSIZE_SENT) 7494b169a6bSchristos type_size += sizeof (ctf_stype_t); 7504b169a6bSchristos else 7514b169a6bSchristos type_size += sizeof (ctf_type_t); 7524b169a6bSchristos 7534b169a6bSchristos switch (kind) 7544b169a6bSchristos { 7554b169a6bSchristos case CTF_K_INTEGER: 7564b169a6bSchristos case CTF_K_FLOAT: 7574b169a6bSchristos type_size += sizeof (uint32_t); 7584b169a6bSchristos break; 7594b169a6bSchristos case CTF_K_ARRAY: 7604b169a6bSchristos type_size += sizeof (ctf_array_t); 7614b169a6bSchristos break; 7624b169a6bSchristos case CTF_K_SLICE: 7634b169a6bSchristos type_size += sizeof (ctf_slice_t); 7644b169a6bSchristos break; 7654b169a6bSchristos case CTF_K_FUNCTION: 7664b169a6bSchristos type_size += sizeof (uint32_t) * (vlen + (vlen & 1)); 7674b169a6bSchristos break; 7684b169a6bSchristos case CTF_K_STRUCT: 7694b169a6bSchristos case CTF_K_UNION: 7704b169a6bSchristos if (type_ctt_size < CTF_LSTRUCT_THRESH) 7714b169a6bSchristos type_size += sizeof (ctf_member_t) * vlen; 7724b169a6bSchristos else 7734b169a6bSchristos type_size += sizeof (ctf_lmember_t) * vlen; 7744b169a6bSchristos break; 7754b169a6bSchristos case CTF_K_ENUM: 7764b169a6bSchristos type_size += sizeof (ctf_enum_t) * vlen; 7774b169a6bSchristos break; 7784b169a6bSchristos } 7794b169a6bSchristos } 7804b169a6bSchristos 781*12989c96Schristos return type_size + fp->ctf_header->cth_stroff - fp->ctf_header->cth_typeoff; 7824b169a6bSchristos } 7834b169a6bSchristos 7844b169a6bSchristos /* Take a final lap through the dynamic type definition list and copy the 7854b169a6bSchristos appropriate type records to the output buffer, noting down the strings as 7864b169a6bSchristos we go. */ 7874b169a6bSchristos 7884b169a6bSchristos static void 7894b169a6bSchristos ctf_emit_type_sect (ctf_dict_t *fp, unsigned char **tptr) 7904b169a6bSchristos { 7914b169a6bSchristos unsigned char *t = *tptr; 7924b169a6bSchristos ctf_dtdef_t *dtd; 7934b169a6bSchristos 7944b169a6bSchristos for (dtd = ctf_list_next (&fp->ctf_dtdefs); 7954b169a6bSchristos dtd != NULL; dtd = ctf_list_next (dtd)) 7964b169a6bSchristos { 7974b169a6bSchristos uint32_t kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info); 7984b169a6bSchristos uint32_t vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info); 7994b169a6bSchristos size_t type_ctt_size = dtd->dtd_data.ctt_size; 8004b169a6bSchristos size_t len; 8014b169a6bSchristos ctf_stype_t *copied; 8024b169a6bSchristos const char *name; 8034b169a6bSchristos size_t i; 8044b169a6bSchristos 8054b169a6bSchristos /* Shrink ctf_type_t-using types from a ctf_type_t to a ctf_stype_t 8064b169a6bSchristos if possible. */ 8074b169a6bSchristos 8084b169a6bSchristos if (kind == CTF_K_STRUCT || kind == CTF_K_UNION) 8094b169a6bSchristos { 8104b169a6bSchristos size_t lsize = CTF_TYPE_LSIZE (&dtd->dtd_data); 8114b169a6bSchristos 8124b169a6bSchristos if (lsize <= CTF_MAX_SIZE) 8134b169a6bSchristos type_ctt_size = lsize; 8144b169a6bSchristos } 8154b169a6bSchristos 8164b169a6bSchristos if (type_ctt_size != CTF_LSIZE_SENT) 8174b169a6bSchristos len = sizeof (ctf_stype_t); 8184b169a6bSchristos else 8194b169a6bSchristos len = sizeof (ctf_type_t); 8204b169a6bSchristos 8214b169a6bSchristos memcpy (t, &dtd->dtd_data, len); 8224b169a6bSchristos copied = (ctf_stype_t *) t; /* name is at the start: constant offset. */ 8234b169a6bSchristos if (copied->ctt_name 8244b169a6bSchristos && (name = ctf_strraw (fp, copied->ctt_name)) != NULL) 8254b169a6bSchristos ctf_str_add_ref (fp, name, &copied->ctt_name); 8264b169a6bSchristos copied->ctt_size = type_ctt_size; 8274b169a6bSchristos t += len; 8284b169a6bSchristos 8294b169a6bSchristos switch (kind) 8304b169a6bSchristos { 8314b169a6bSchristos case CTF_K_INTEGER: 8324b169a6bSchristos case CTF_K_FLOAT: 8334b169a6bSchristos memcpy (t, dtd->dtd_vlen, sizeof (uint32_t)); 8344b169a6bSchristos t += sizeof (uint32_t); 8354b169a6bSchristos break; 8364b169a6bSchristos 8374b169a6bSchristos case CTF_K_SLICE: 8384b169a6bSchristos memcpy (t, dtd->dtd_vlen, sizeof (struct ctf_slice)); 8394b169a6bSchristos t += sizeof (struct ctf_slice); 8404b169a6bSchristos break; 8414b169a6bSchristos 8424b169a6bSchristos case CTF_K_ARRAY: 8434b169a6bSchristos memcpy (t, dtd->dtd_vlen, sizeof (struct ctf_array)); 8444b169a6bSchristos t += sizeof (struct ctf_array); 8454b169a6bSchristos break; 8464b169a6bSchristos 8474b169a6bSchristos case CTF_K_FUNCTION: 8484b169a6bSchristos /* Functions with no args also have no vlen. */ 8494b169a6bSchristos if (dtd->dtd_vlen) 8504b169a6bSchristos memcpy (t, dtd->dtd_vlen, sizeof (uint32_t) * (vlen + (vlen & 1))); 8514b169a6bSchristos t += sizeof (uint32_t) * (vlen + (vlen & 1)); 8524b169a6bSchristos break; 8534b169a6bSchristos 8544b169a6bSchristos /* These need to be copied across element by element, depending on 8554b169a6bSchristos their ctt_size. */ 8564b169a6bSchristos case CTF_K_STRUCT: 8574b169a6bSchristos case CTF_K_UNION: 8584b169a6bSchristos { 8594b169a6bSchristos ctf_lmember_t *dtd_vlen = (ctf_lmember_t *) dtd->dtd_vlen; 8604b169a6bSchristos ctf_lmember_t *t_lvlen = (ctf_lmember_t *) t; 8614b169a6bSchristos ctf_member_t *t_vlen = (ctf_member_t *) t; 8624b169a6bSchristos 8634b169a6bSchristos for (i = 0; i < vlen; i++) 8644b169a6bSchristos { 8654b169a6bSchristos const char *name = ctf_strraw (fp, dtd_vlen[i].ctlm_name); 8664b169a6bSchristos 8674b169a6bSchristos ctf_str_add_ref (fp, name, &dtd_vlen[i].ctlm_name); 8684b169a6bSchristos 8694b169a6bSchristos if (type_ctt_size < CTF_LSTRUCT_THRESH) 8704b169a6bSchristos { 8714b169a6bSchristos t_vlen[i].ctm_name = dtd_vlen[i].ctlm_name; 8724b169a6bSchristos t_vlen[i].ctm_type = dtd_vlen[i].ctlm_type; 8734b169a6bSchristos t_vlen[i].ctm_offset = CTF_LMEM_OFFSET (&dtd_vlen[i]); 8744b169a6bSchristos ctf_str_add_ref (fp, name, &t_vlen[i].ctm_name); 8754b169a6bSchristos } 8764b169a6bSchristos else 8774b169a6bSchristos { 8784b169a6bSchristos t_lvlen[i] = dtd_vlen[i]; 8794b169a6bSchristos ctf_str_add_ref (fp, name, &t_lvlen[i].ctlm_name); 8804b169a6bSchristos } 8814b169a6bSchristos } 8824b169a6bSchristos } 8834b169a6bSchristos 8844b169a6bSchristos if (type_ctt_size < CTF_LSTRUCT_THRESH) 8854b169a6bSchristos t += sizeof (ctf_member_t) * vlen; 8864b169a6bSchristos else 8874b169a6bSchristos t += sizeof (ctf_lmember_t) * vlen; 8884b169a6bSchristos break; 8894b169a6bSchristos 8904b169a6bSchristos case CTF_K_ENUM: 8914b169a6bSchristos { 8924b169a6bSchristos ctf_enum_t *dtd_vlen = (struct ctf_enum *) dtd->dtd_vlen; 8934b169a6bSchristos ctf_enum_t *t_vlen = (struct ctf_enum *) t; 8944b169a6bSchristos 8954b169a6bSchristos memcpy (t, dtd->dtd_vlen, sizeof (struct ctf_enum) * vlen); 8964b169a6bSchristos for (i = 0; i < vlen; i++) 8974b169a6bSchristos { 8984b169a6bSchristos const char *name = ctf_strraw (fp, dtd_vlen[i].cte_name); 8994b169a6bSchristos 9004b169a6bSchristos ctf_str_add_ref (fp, name, &t_vlen[i].cte_name); 9014b169a6bSchristos ctf_str_add_ref (fp, name, &dtd_vlen[i].cte_name); 9024b169a6bSchristos } 9034b169a6bSchristos t += sizeof (struct ctf_enum) * vlen; 9044b169a6bSchristos 9054b169a6bSchristos break; 9064b169a6bSchristos } 9074b169a6bSchristos } 9084b169a6bSchristos } 9094b169a6bSchristos 9104b169a6bSchristos *tptr = t; 9114b169a6bSchristos } 9124b169a6bSchristos 9134b169a6bSchristos /* Variable section. */ 9144b169a6bSchristos 9154b169a6bSchristos /* Sort a newly-constructed static variable array. */ 9164b169a6bSchristos 9174b169a6bSchristos typedef struct ctf_sort_var_arg_cb 9184b169a6bSchristos { 9194b169a6bSchristos ctf_dict_t *fp; 9204b169a6bSchristos ctf_strs_t *strtab; 9214b169a6bSchristos } ctf_sort_var_arg_cb_t; 9224b169a6bSchristos 9234b169a6bSchristos static int 9244b169a6bSchristos ctf_sort_var (const void *one_, const void *two_, void *arg_) 9254b169a6bSchristos { 9264b169a6bSchristos const ctf_varent_t *one = one_; 9274b169a6bSchristos const ctf_varent_t *two = two_; 9284b169a6bSchristos ctf_sort_var_arg_cb_t *arg = arg_; 9294b169a6bSchristos 9304b169a6bSchristos return (strcmp (ctf_strraw_explicit (arg->fp, one->ctv_name, arg->strtab), 9314b169a6bSchristos ctf_strraw_explicit (arg->fp, two->ctv_name, arg->strtab))); 9324b169a6bSchristos } 9334b169a6bSchristos 9344b169a6bSchristos /* Overall serialization. */ 9354b169a6bSchristos 936*12989c96Schristos /* Emit a new CTF dict which is a serialized copy of this one: also reify 937*12989c96Schristos the string table and update all offsets in the current dict suitably. 938*12989c96Schristos (This simplifies ctf-string.c a little, at the cost of storing a second 939*12989c96Schristos copy of the strtab if this dict was originally read in via ctf_open.) 940*12989c96Schristos 941*12989c96Schristos Other aspects of the existing dict are unchanged, although some 942*12989c96Schristos static entries may be duplicated in the dynamic state (which should 943*12989c96Schristos have no effect on visible operation). */ 944*12989c96Schristos 945*12989c96Schristos static unsigned char * 946*12989c96Schristos ctf_serialize (ctf_dict_t *fp, size_t *bufsiz) 9474b169a6bSchristos { 9484b169a6bSchristos ctf_header_t hdr, *hdrp; 9494b169a6bSchristos ctf_dvdef_t *dvd; 9504b169a6bSchristos ctf_varent_t *dvarents; 951*12989c96Schristos const ctf_strs_writable_t *strtab; 952*12989c96Schristos int sym_functions = 0; 9534b169a6bSchristos 9544b169a6bSchristos unsigned char *t; 9554b169a6bSchristos unsigned long i; 9564b169a6bSchristos size_t buf_size, type_size, objt_size, func_size; 9574b169a6bSchristos size_t funcidx_size, objtidx_size; 9584b169a6bSchristos size_t nvars; 9594b169a6bSchristos unsigned char *buf = NULL, *newbuf; 9604b169a6bSchristos 9614b169a6bSchristos emit_symtypetab_state_t symstate; 9624b169a6bSchristos memset (&symstate, 0, sizeof (emit_symtypetab_state_t)); 9634b169a6bSchristos 9644b169a6bSchristos /* Fill in an initial CTF header. We will leave the label, object, 9654b169a6bSchristos and function sections empty and only output a header, type section, 9664b169a6bSchristos and string table. The type section begins at a 4-byte aligned 9674b169a6bSchristos boundary past the CTF header itself (at relative offset zero). The flag 9684b169a6bSchristos indicating a new-style function info section (an array of CTF_K_FUNCTION 9694b169a6bSchristos type IDs in the types section) is flipped on. */ 9704b169a6bSchristos 9714b169a6bSchristos memset (&hdr, 0, sizeof (hdr)); 9724b169a6bSchristos hdr.cth_magic = CTF_MAGIC; 9734b169a6bSchristos hdr.cth_version = CTF_VERSION; 9744b169a6bSchristos 9754b169a6bSchristos /* This is a new-format func info section, and the symtab and strtab come out 9764b169a6bSchristos of the dynsym and dynstr these days. */ 9774b169a6bSchristos hdr.cth_flags = (CTF_F_NEWFUNCINFO | CTF_F_DYNSTR); 9784b169a6bSchristos 979*12989c96Schristos /* Propagate all symbols in the symtypetabs into the dynamic state, so that 980*12989c96Schristos we can put them back in the right order. Symbols already in the dynamic 981*12989c96Schristos state, likely due to repeated serialization, are left unchanged. */ 982*12989c96Schristos do 983*12989c96Schristos { 984*12989c96Schristos ctf_next_t *it = NULL; 985*12989c96Schristos const char *sym_name; 986*12989c96Schristos ctf_id_t sym; 987*12989c96Schristos 988*12989c96Schristos while ((sym = ctf_symbol_next_static (fp, &it, &sym_name, 989*12989c96Schristos sym_functions)) != CTF_ERR) 990*12989c96Schristos if ((ctf_add_funcobjt_sym_forced (fp, sym_functions, sym_name, sym)) < 0) 991*12989c96Schristos if (ctf_errno (fp) != ECTF_DUPLICATE) 992*12989c96Schristos return NULL; /* errno is set for us. */ 993*12989c96Schristos 994*12989c96Schristos if (ctf_errno (fp) != ECTF_NEXT_END) 995*12989c96Schristos return NULL; /* errno is set for us. */ 996*12989c96Schristos } while (sym_functions++ < 1); 997*12989c96Schristos 998*12989c96Schristos /* Figure out how big the symtypetabs are now. */ 999*12989c96Schristos 10004b169a6bSchristos if (ctf_symtypetab_sect_sizes (fp, &symstate, &hdr, &objt_size, &func_size, 10014b169a6bSchristos &objtidx_size, &funcidx_size) < 0) 1002*12989c96Schristos return NULL; /* errno is set for us. */ 1003*12989c96Schristos 1004*12989c96Schristos /* Propagate all vars into the dynamic state, so we can put them back later. 1005*12989c96Schristos Variables already in the dynamic state, likely due to repeated 1006*12989c96Schristos serialization, are left unchanged. */ 1007*12989c96Schristos 1008*12989c96Schristos for (i = 0; i < fp->ctf_nvars; i++) 1009*12989c96Schristos { 1010*12989c96Schristos const char *name = ctf_strptr (fp, fp->ctf_vars[i].ctv_name); 1011*12989c96Schristos 1012*12989c96Schristos if (name != NULL && !ctf_dvd_lookup (fp, name)) 1013*12989c96Schristos if (ctf_add_variable_forced (fp, name, fp->ctf_vars[i].ctv_type) < 0) 1014*12989c96Schristos return NULL; /* errno is set for us. */ 1015*12989c96Schristos } 10164b169a6bSchristos 10174b169a6bSchristos for (nvars = 0, dvd = ctf_list_next (&fp->ctf_dvdefs); 10184b169a6bSchristos dvd != NULL; dvd = ctf_list_next (dvd), nvars++); 10194b169a6bSchristos 10204b169a6bSchristos type_size = ctf_type_sect_size (fp); 10214b169a6bSchristos 10224b169a6bSchristos /* Compute the size of the CTF buffer we need, sans only the string table, 10234b169a6bSchristos then allocate a new buffer and memcpy the finished header to the start of 10244b169a6bSchristos the buffer. (We will adjust this later with strtab length info.) */ 10254b169a6bSchristos 10264b169a6bSchristos hdr.cth_lbloff = hdr.cth_objtoff = 0; 10274b169a6bSchristos hdr.cth_funcoff = hdr.cth_objtoff + objt_size; 10284b169a6bSchristos hdr.cth_objtidxoff = hdr.cth_funcoff + func_size; 10294b169a6bSchristos hdr.cth_funcidxoff = hdr.cth_objtidxoff + objtidx_size; 10304b169a6bSchristos hdr.cth_varoff = hdr.cth_funcidxoff + funcidx_size; 10314b169a6bSchristos hdr.cth_typeoff = hdr.cth_varoff + (nvars * sizeof (ctf_varent_t)); 10324b169a6bSchristos hdr.cth_stroff = hdr.cth_typeoff + type_size; 10334b169a6bSchristos hdr.cth_strlen = 0; 10344b169a6bSchristos 10354b169a6bSchristos buf_size = sizeof (ctf_header_t) + hdr.cth_stroff + hdr.cth_strlen; 10364b169a6bSchristos 10374b169a6bSchristos if ((buf = malloc (buf_size)) == NULL) 1038*12989c96Schristos { 1039*12989c96Schristos ctf_set_errno (fp, EAGAIN); 1040*12989c96Schristos return NULL; 1041*12989c96Schristos } 10424b169a6bSchristos 10434b169a6bSchristos memcpy (buf, &hdr, sizeof (ctf_header_t)); 10444b169a6bSchristos t = (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_objtoff; 10454b169a6bSchristos 10464b169a6bSchristos hdrp = (ctf_header_t *) buf; 10474b169a6bSchristos if ((fp->ctf_flags & LCTF_CHILD) && (fp->ctf_parname != NULL)) 10484b169a6bSchristos ctf_str_add_ref (fp, fp->ctf_parname, &hdrp->cth_parname); 10494b169a6bSchristos if (fp->ctf_cuname != NULL) 10504b169a6bSchristos ctf_str_add_ref (fp, fp->ctf_cuname, &hdrp->cth_cuname); 10514b169a6bSchristos 10524b169a6bSchristos if (ctf_emit_symtypetab_sects (fp, &symstate, &t, objt_size, func_size, 10534b169a6bSchristos objtidx_size, funcidx_size) < 0) 10544b169a6bSchristos goto err; 10554b169a6bSchristos 10564b169a6bSchristos assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_varoff); 10574b169a6bSchristos 10584b169a6bSchristos /* Work over the variable list, translating everything into ctf_varent_t's and 10594b169a6bSchristos prepping the string table. */ 10604b169a6bSchristos 10614b169a6bSchristos dvarents = (ctf_varent_t *) t; 10624b169a6bSchristos for (i = 0, dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; 10634b169a6bSchristos dvd = ctf_list_next (dvd), i++) 10644b169a6bSchristos { 10654b169a6bSchristos ctf_varent_t *var = &dvarents[i]; 10664b169a6bSchristos 10674b169a6bSchristos ctf_str_add_ref (fp, dvd->dvd_name, &var->ctv_name); 10684b169a6bSchristos var->ctv_type = (uint32_t) dvd->dvd_type; 10694b169a6bSchristos } 10704b169a6bSchristos assert (i == nvars); 10714b169a6bSchristos 10724b169a6bSchristos t += sizeof (ctf_varent_t) * nvars; 10734b169a6bSchristos 10744b169a6bSchristos assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_typeoff); 10754b169a6bSchristos 1076*12989c96Schristos /* Copy in existing static types, then emit new dynamic types. */ 1077*12989c96Schristos 1078*12989c96Schristos memcpy (t, fp->ctf_buf + fp->ctf_header->cth_typeoff, 1079*12989c96Schristos fp->ctf_header->cth_stroff - fp->ctf_header->cth_typeoff); 1080*12989c96Schristos t += fp->ctf_header->cth_stroff - fp->ctf_header->cth_typeoff; 10814b169a6bSchristos ctf_emit_type_sect (fp, &t); 10824b169a6bSchristos 10834b169a6bSchristos assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_stroff); 10844b169a6bSchristos 10854b169a6bSchristos /* Construct the final string table and fill out all the string refs with the 1086*12989c96Schristos final offsets. */ 10874b169a6bSchristos 1088*12989c96Schristos strtab = ctf_str_write_strtab (fp); 1089*12989c96Schristos 1090*12989c96Schristos if (strtab == NULL) 10914b169a6bSchristos goto oom; 10924b169a6bSchristos 10934b169a6bSchristos /* Now the string table is constructed, we can sort the buffer of 10944b169a6bSchristos ctf_varent_t's. */ 1095*12989c96Schristos ctf_sort_var_arg_cb_t sort_var_arg = { fp, (ctf_strs_t *) strtab }; 10964b169a6bSchristos ctf_qsort_r (dvarents, nvars, sizeof (ctf_varent_t), ctf_sort_var, 10974b169a6bSchristos &sort_var_arg); 10984b169a6bSchristos 1099*12989c96Schristos if ((newbuf = realloc (buf, buf_size + strtab->cts_len)) == NULL) 11004b169a6bSchristos goto oom; 1101*12989c96Schristos 11024b169a6bSchristos buf = newbuf; 1103*12989c96Schristos memcpy (buf + buf_size, strtab->cts_strs, strtab->cts_len); 11044b169a6bSchristos hdrp = (ctf_header_t *) buf; 1105*12989c96Schristos hdrp->cth_strlen = strtab->cts_len; 11064b169a6bSchristos buf_size += hdrp->cth_strlen; 1107*12989c96Schristos *bufsiz = buf_size; 11084b169a6bSchristos 1109*12989c96Schristos return buf; 11104b169a6bSchristos 11114b169a6bSchristos oom: 1112*12989c96Schristos ctf_set_errno (fp, EAGAIN); 11134b169a6bSchristos err: 11144b169a6bSchristos free (buf); 1115*12989c96Schristos return NULL; /* errno is set for us. */ 11164b169a6bSchristos } 11174b169a6bSchristos 11184b169a6bSchristos /* File writing. */ 11194b169a6bSchristos 11204b169a6bSchristos /* Write the compressed CTF data stream to the specified gzFile descriptor. The 11214b169a6bSchristos whole stream is compressed, and cannot be read by CTF opening functions in 11224b169a6bSchristos this library until it is decompressed. (The functions below this one leave 11234b169a6bSchristos the header uncompressed, and the CTF opening functions work on them without 11244b169a6bSchristos manual decompression.) 11254b169a6bSchristos 11264b169a6bSchristos No support for (testing-only) endian-flipping. */ 11274b169a6bSchristos int 11284b169a6bSchristos ctf_gzwrite (ctf_dict_t *fp, gzFile fd) 11294b169a6bSchristos { 1130*12989c96Schristos unsigned char *buf; 1131*12989c96Schristos unsigned char *p; 1132*12989c96Schristos size_t bufsiz; 1133*12989c96Schristos size_t len, written = 0; 11344b169a6bSchristos 1135*12989c96Schristos if ((buf = ctf_serialize (fp, &bufsiz)) == NULL) 1136*12989c96Schristos return -1; /* errno is set for us. */ 1137*12989c96Schristos 1138*12989c96Schristos p = buf; 1139*12989c96Schristos while (written < bufsiz) 11404b169a6bSchristos { 1141*12989c96Schristos if ((len = gzwrite (fd, p, bufsiz - written)) <= 0) 1142*12989c96Schristos { 1143*12989c96Schristos free (buf); 11444b169a6bSchristos return (ctf_set_errno (fp, errno)); 1145*12989c96Schristos } 1146*12989c96Schristos written += len; 1147*12989c96Schristos p += len; 11484b169a6bSchristos } 11494b169a6bSchristos 1150*12989c96Schristos free (buf); 11514b169a6bSchristos return 0; 11524b169a6bSchristos } 11534b169a6bSchristos 11544b169a6bSchristos /* Optionally compress the specified CTF data stream and return it as a new 11554b169a6bSchristos dynamically-allocated string. Possibly write it with reversed 11564b169a6bSchristos endianness. */ 11574b169a6bSchristos unsigned char * 11584b169a6bSchristos ctf_write_mem (ctf_dict_t *fp, size_t *size, size_t threshold) 11594b169a6bSchristos { 1160*12989c96Schristos unsigned char *rawbuf; 1161*12989c96Schristos unsigned char *buf = NULL; 11624b169a6bSchristos unsigned char *bp; 1163*12989c96Schristos ctf_header_t *rawhp, *hp; 1164*12989c96Schristos unsigned char *src; 1165*12989c96Schristos size_t rawbufsiz; 1166*12989c96Schristos size_t alloc_len = 0; 1167*12989c96Schristos int uncompressed = 0; 11684b169a6bSchristos int flip_endian; 11694b169a6bSchristos int rc; 11704b169a6bSchristos 11714b169a6bSchristos flip_endian = getenv ("LIBCTF_WRITE_FOREIGN_ENDIAN") != NULL; 11724b169a6bSchristos 1173*12989c96Schristos if ((rawbuf = ctf_serialize (fp, &rawbufsiz)) == NULL) 11744b169a6bSchristos return NULL; /* errno is set for us. */ 11754b169a6bSchristos 1176*12989c96Schristos if (!ctf_assert (fp, rawbufsiz >= sizeof (ctf_header_t))) 1177*12989c96Schristos goto err; 1178*12989c96Schristos 1179*12989c96Schristos if (rawbufsiz >= threshold) 1180*12989c96Schristos alloc_len = compressBound (rawbufsiz - sizeof (ctf_header_t)) 1181*12989c96Schristos + sizeof (ctf_header_t); 1182*12989c96Schristos 1183*12989c96Schristos /* Trivial operation if the buffer is incompressible or too small to bother 1184*12989c96Schristos compressing, and we're not doing a forced write-time flip. */ 1185*12989c96Schristos 1186*12989c96Schristos if (rawbufsiz < threshold || rawbufsiz < alloc_len) 1187*12989c96Schristos { 1188*12989c96Schristos alloc_len = rawbufsiz; 1189*12989c96Schristos uncompressed = 1; 1190*12989c96Schristos } 1191*12989c96Schristos 1192*12989c96Schristos if (!flip_endian && uncompressed) 1193*12989c96Schristos { 1194*12989c96Schristos *size = rawbufsiz; 1195*12989c96Schristos return rawbuf; 1196*12989c96Schristos } 1197*12989c96Schristos 1198*12989c96Schristos if ((buf = malloc (alloc_len)) == NULL) 11994b169a6bSchristos { 12004b169a6bSchristos ctf_set_errno (fp, ENOMEM); 12014b169a6bSchristos ctf_err_warn (fp, 0, 0, _("ctf_write_mem: cannot allocate %li bytes"), 1202*12989c96Schristos (unsigned long) (alloc_len)); 1203*12989c96Schristos goto err; 12044b169a6bSchristos } 12054b169a6bSchristos 1206*12989c96Schristos rawhp = (ctf_header_t *) rawbuf; 12074b169a6bSchristos hp = (ctf_header_t *) buf; 1208*12989c96Schristos memcpy (hp, rawbuf, sizeof (ctf_header_t)); 1209*12989c96Schristos bp = buf + sizeof (ctf_header_t); 1210*12989c96Schristos *size = sizeof (ctf_header_t); 12114b169a6bSchristos 1212*12989c96Schristos if (!uncompressed) 12134b169a6bSchristos hp->cth_flags |= CTF_F_COMPRESS; 12144b169a6bSchristos 1215*12989c96Schristos src = rawbuf + sizeof (ctf_header_t); 12164b169a6bSchristos 12174b169a6bSchristos if (flip_endian) 12184b169a6bSchristos { 12194b169a6bSchristos ctf_flip_header (hp); 1220*12989c96Schristos if (ctf_flip (fp, rawhp, src, 1) < 0) 1221*12989c96Schristos goto err; /* errno is set for us. */ 12224b169a6bSchristos } 12234b169a6bSchristos 1224*12989c96Schristos if (!uncompressed) 12254b169a6bSchristos { 1226*12989c96Schristos size_t compress_len = alloc_len - sizeof (ctf_header_t); 1227*12989c96Schristos 12284b169a6bSchristos if ((rc = compress (bp, (uLongf *) &compress_len, 1229*12989c96Schristos src, rawbufsiz - sizeof (ctf_header_t))) != Z_OK) 12304b169a6bSchristos { 12314b169a6bSchristos ctf_set_errno (fp, ECTF_COMPRESS); 12324b169a6bSchristos ctf_err_warn (fp, 0, 0, _("zlib deflate err: %s"), zError (rc)); 1233*12989c96Schristos goto err; 12344b169a6bSchristos } 12354b169a6bSchristos *size += compress_len; 12364b169a6bSchristos } 1237*12989c96Schristos else 1238*12989c96Schristos { 1239*12989c96Schristos memcpy (bp, src, rawbufsiz - sizeof (ctf_header_t)); 1240*12989c96Schristos *size += rawbufsiz - sizeof (ctf_header_t); 1241*12989c96Schristos } 12424b169a6bSchristos 1243*12989c96Schristos free (rawbuf); 12444b169a6bSchristos return buf; 1245*12989c96Schristos err: 1246*12989c96Schristos free (buf); 1247*12989c96Schristos free (rawbuf); 1248*12989c96Schristos return NULL; 12494b169a6bSchristos } 12504b169a6bSchristos 12514b169a6bSchristos /* Compress the specified CTF data stream and write it to the specified file 12524b169a6bSchristos descriptor. */ 12534b169a6bSchristos int 12544b169a6bSchristos ctf_compress_write (ctf_dict_t *fp, int fd) 12554b169a6bSchristos { 12564b169a6bSchristos unsigned char *buf; 12574b169a6bSchristos unsigned char *bp; 12584b169a6bSchristos size_t tmp; 12594b169a6bSchristos ssize_t buf_len; 12604b169a6bSchristos ssize_t len; 12614b169a6bSchristos int err = 0; 12624b169a6bSchristos 12634b169a6bSchristos if ((buf = ctf_write_mem (fp, &tmp, 0)) == NULL) 12644b169a6bSchristos return -1; /* errno is set for us. */ 12654b169a6bSchristos 12664b169a6bSchristos buf_len = tmp; 12674b169a6bSchristos bp = buf; 12684b169a6bSchristos 12694b169a6bSchristos while (buf_len > 0) 12704b169a6bSchristos { 12714b169a6bSchristos if ((len = write (fd, bp, buf_len)) < 0) 12724b169a6bSchristos { 12734b169a6bSchristos err = ctf_set_errno (fp, errno); 12744b169a6bSchristos ctf_err_warn (fp, 0, 0, _("ctf_compress_write: error writing")); 12754b169a6bSchristos goto ret; 12764b169a6bSchristos } 12774b169a6bSchristos buf_len -= len; 12784b169a6bSchristos bp += len; 12794b169a6bSchristos } 12804b169a6bSchristos 12814b169a6bSchristos ret: 12824b169a6bSchristos free (buf); 12834b169a6bSchristos return err; 12844b169a6bSchristos } 12854b169a6bSchristos 12864b169a6bSchristos /* Write the uncompressed CTF data stream to the specified file descriptor. */ 12874b169a6bSchristos int 12884b169a6bSchristos ctf_write (ctf_dict_t *fp, int fd) 12894b169a6bSchristos { 12904b169a6bSchristos unsigned char *buf; 12914b169a6bSchristos unsigned char *bp; 12924b169a6bSchristos size_t tmp; 12934b169a6bSchristos ssize_t buf_len; 12944b169a6bSchristos ssize_t len; 12954b169a6bSchristos int err = 0; 12964b169a6bSchristos 12974b169a6bSchristos if ((buf = ctf_write_mem (fp, &tmp, (size_t) -1)) == NULL) 12984b169a6bSchristos return -1; /* errno is set for us. */ 12994b169a6bSchristos 13004b169a6bSchristos buf_len = tmp; 13014b169a6bSchristos bp = buf; 13024b169a6bSchristos 13034b169a6bSchristos while (buf_len > 0) 13044b169a6bSchristos { 13054b169a6bSchristos if ((len = write (fd, bp, buf_len)) < 0) 13064b169a6bSchristos { 13074b169a6bSchristos err = ctf_set_errno (fp, errno); 13084b169a6bSchristos ctf_err_warn (fp, 0, 0, _("ctf_compress_write: error writing")); 13094b169a6bSchristos goto ret; 13104b169a6bSchristos } 13114b169a6bSchristos buf_len -= len; 13124b169a6bSchristos bp += len; 13134b169a6bSchristos } 13144b169a6bSchristos 13154b169a6bSchristos ret: 13164b169a6bSchristos free (buf); 13174b169a6bSchristos return err; 13184b169a6bSchristos } 1319