| /* CTF type deduplication. | 
 |    Copyright (C) 2019-2022 Free Software Foundation, Inc. | 
 |  | 
 |    This file is part of libctf. | 
 |  | 
 |    libctf is free software; you can redistribute it and/or modify it under | 
 |    the terms of the GNU General Public License as published by the Free | 
 |    Software Foundation; either version 3, or (at your option) any later | 
 |    version. | 
 |  | 
 |    This program is distributed in the hope that it will be useful, but | 
 |    WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 
 |    See the GNU General Public License for more details. | 
 |  | 
 |    You should have received a copy of the GNU General Public License | 
 |    along with this program; see the file COPYING.  If not see | 
 |    <http://www.gnu.org/licenses/>.  */ | 
 |  | 
 | #include <ctf-impl.h> | 
 | #include <string.h> | 
 | #include <errno.h> | 
 | #include <assert.h> | 
 | #include "hashtab.h" | 
 |  | 
 | /* (In the below, relevant functions are named in square brackets.)  */ | 
 |  | 
 | /* Type deduplication is a three-phase process: | 
 |  | 
 |     [ctf_dedup, ctf_dedup_hash_type, ctf_dedup_rhash_type] | 
 |     1) come up with unambiguous hash values for all types: no two types may have | 
 |        the same hash value, and any given type should have only one hash value | 
 |        (for optimal deduplication). | 
 |  | 
 |     [ctf_dedup, ctf_dedup_detect_name_ambiguity, | 
 |      ctf_dedup_conflictify_unshared, ctf_dedup_mark_conflicting_hash] | 
 |     2) mark those distinct types with names that collide (and thus cannot be | 
 |        declared simultaneously in the same translation unit) as conflicting, and | 
 |        recursively mark all types that cite one of those types as conflicting as | 
 |        well.  Possibly mark all types cited in only one TU as conflicting, if | 
 |        the CTF_LINK_SHARE_DUPLICATED link mode is active. | 
 |  | 
 |     [ctf_dedup_emit, ctf_dedup_emit_struct_members, ctf_dedup_id_to_target] | 
 |     3) emit all the types, one hash value at a time.  Types not marked | 
 |        conflicting are emitted once, into the shared dictionary: types marked | 
 |        conflicting are emitted once per TU into a dictionary corresponding to | 
 |        each TU in which they appear.  Structs marked conflicting get at the very | 
 |        least a forward emitted into the shared dict so that other dicts can cite | 
 |        it if needed. | 
 |  | 
 |    [id_to_packed_id] | 
 |    This all works over an array of inputs (usually in the same order as the | 
 |    inputs on the link line).  We don't use the ctf_link_inputs hash directly | 
 |    because it is convenient to be able to address specific input types as a | 
 |    *global type ID* or 'GID', a pair of an array offset and a ctf_id_t.  Since | 
 |    both are already 32 bits or less or can easily be constrained to that range, | 
 |    we can pack them both into a single 64-bit hash word for easy lookups, which | 
 |    would be much more annoying to do with a ctf_dict_t * and a ctf_id_t.  (On | 
 |    32-bit platforms, we must do that anyway, since pointers, and thus hash keys | 
 |    and values, are only 32 bits wide).  We track which inputs are parents of | 
 |    which other inputs so that we can correctly recognize that types we have | 
 |    traversed in children may cite types in parents, and so that we can process | 
 |    the parents first.) | 
 |  | 
 |    Note that thanks to ld -r, the deduplicator can be fed its own output, so the | 
 |    inputs may themselves have child dicts.  Since we need to support this usage | 
 |    anyway, we can use it in one other place.  If the caller finds translation | 
 |    units to be too small a unit ambiguous types, links can be 'cu-mapped', where | 
 |    the caller provides a mapping of input TU names to output child dict names. | 
 |    This mapping can fuse many child TUs into one potential child dict, so that | 
 |    ambiguous types in any of those input TUs go into the same child dict. | 
 |    When a many:1 cu-mapping is detected, the ctf_dedup machinery is called | 
 |    repeatedly, once for every output name that has more than one input, to fuse | 
 |    all the input TUs associated with a given output dict into one, and once again | 
 |    as normal to deduplicate all those intermediate outputs (and any 1:1 inputs) | 
 |    together.  This has much higher memory usage than otherwise, because in the | 
 |    intermediate state, all the output TUs are in memory at once and cannot be | 
 |    lazily opened.  It also has implications for the emission code: if types | 
 |    appear ambiguously in multiple input TUs that are all mapped to the same | 
 |    child dict, we cannot put them in children in the cu-mapping link phase | 
 |    because this output is meant to *become* a child in the next link stage and | 
 |    parent/child relationships are only one level deep: so instead, we just hide | 
 |    all but one of the ambiguous types. | 
 |  | 
 |    There are a few other subtleties here that make this more complex than it | 
 |    seems.  Let's go over the steps above in more detail. | 
 |  | 
 |    1) HASHING. | 
 |  | 
 |    [ctf_dedup_hash_type, ctf_dedup_rhash_type] | 
 |    Hashing proceeds recursively, mixing in the properties of each input type | 
 |    (including its name, if any), and then adding the hash values of every type | 
 |    cited by that type.  The result is stashed in the cd_type_hashes so other | 
 |    phases can find the hash values of input types given their IDs, and so that | 
 |    if we encounter this type again while hashing we can just return its hash | 
 |    value: it is also stashed in the *output mapping*, a mapping from hash value | 
 |    to the set of GIDs corresponding to that type in all inputs.  We also keep | 
 |    track of the GID of the first appearance of the type in any input (in | 
 |    cd_output_first_gid), and the GID of structs, unions, and forwards that only | 
 |    appear in one TU (in cd_struct_origin).  See below for where these things are | 
 |    used. | 
 |  | 
 |    Everything in this phase is time-critical, because it is operating over | 
 |    non-deduplicated types and so may have hundreds or thousands of times the | 
 |    data volume to deal with than later phases.  Trace output is hidden behind | 
 |    ENABLE_LIBCTF_HASH_DEBUGGING to prevent the sheer number of calls to | 
 |    ctf_dprintf from slowing things down (tenfold slowdowns are observed purely | 
 |    from the calls to ctf_dprintf(), even with debugging switched off), and keep | 
 |    down the volume of output (hundreds of gigabytes of debug output are not | 
 |    uncommon on larger links). | 
 |  | 
 |    We have to do *something* about potential cycles in the type graph.  We'd | 
 |    like to avoid emitting forwards in the final output if possible, because | 
 |    forwards aren't much use: they have no members.  We are mostly saved from | 
 |    needing to worry about this at emission time by ctf_add_struct*() | 
 |    automatically replacing newly-created forwards when the real struct/union | 
 |    comes along.  So we only have to avoid getting stuck in cycles during the | 
 |    hashing phase, while also not confusing types that cite members that are | 
 |    structs with each other.  It is easiest to solve this problem by noting two | 
 |    things: | 
 |  | 
 |     - all cycles in C depend on the presence of tagged structs/unions | 
 |     - all tagged structs/unions have a unique name they can be disambiguated by | 
 |  | 
 |    [ctf_dedup_is_stub] | 
 |    This means that we can break all cycles by ceasing to hash in cited types at | 
 |    every tagged struct/union and instead hashing in a stub consisting of the | 
 |    struct/union's *decorated name*, which is the name preceded by "s " or "u " | 
 |    depending on the namespace (cached in cd_decorated_names).  Forwards are | 
 |    decorated identically (so a forward to "struct foo" would be represented as | 
 |    "s foo"): this means that a citation of a forward to a type and a citation of | 
 |    a concrete definition of a type with the same name ends up getting the same | 
 |    hash value. | 
 |  | 
 |    Of course, it is quite possible to have two TUs with structs with the same | 
 |    name and different definitions, but that's OK because when we scan for types | 
 |    with ambiguous names we will identify these and mark them conflicting. | 
 |  | 
 |    We populate one thing to help conflictedness marking.  No unconflicted type | 
 |    may cite a conflicted one, but this means that conflictedness marking must | 
 |    walk from types to the types that cite them, which is the opposite of the | 
 |    usual order.  We can make this easier to do by constructing a *citers* graph | 
 |    in cd_citers, which points from types to the types that cite them: because we | 
 |    emit forwards corresponding to every conflicted struct/union, we don't need | 
 |    to do this for citations of structs/unions by other types.  This is very | 
 |    convenient for us, because that's the only type we don't traverse | 
 |    recursively: so we can construct the citers graph at the same time as we | 
 |    hash, rather than needing to add an extra pass.  (This graph is a dynhash of | 
 |    *type hash values*, so it's small: in effect it is automatically | 
 |    deduplicated.) | 
 |  | 
 |    2) COLLISIONAL MARKING. | 
 |  | 
 |    [ctf_dedup_detect_name_ambiguity, ctf_dedup_mark_conflicting_hash] | 
 |    We identify types whose names collide during the hashing process, and count | 
 |    the rough number of uses of each name (caching may throw it off a bit: this | 
 |    doesn't need to be accurate).  We then mark the less-frequently-cited types | 
 |    with each names conflicting: the most-frequently-cited one goes into the | 
 |    shared type dictionary, while all others are duplicated into per-TU | 
 |    dictionaries, named after the input TU, that have the shared dictionary as a | 
 |    parent.  For structures and unions this is not quite good enough: we'd like | 
 |    to have citations of forwards to ambiguously named structures and unions | 
 |    *stay* as citations of forwards, so that the user can tell that the caller | 
 |    didn't actually know which structure definition was meant: but if we put one | 
 |    of those structures into the shared dictionary, it would supplant and replace | 
 |    the forward, leaving no sign.  So structures and unions do not take part in | 
 |    this popularity contest: if their names are ambiguous, they are just | 
 |    duplicated, and only a forward appears in the shared dict. | 
 |  | 
 |    [ctf_dedup_propagate_conflictedness] | 
 |    The process of marking types conflicted is itself recursive: we recursively | 
 |    traverse the cd_citers graph populated in the hashing pass above and mark | 
 |    everything that we encounter conflicted (without wasting time re-marking | 
 |    anything that is already marked).  This naturally terminates just where we | 
 |    want it to (at types that are cited by no other types, and at structures and | 
 |    unions) and suffices to ensure that types that cite conflicted types are | 
 |    always marked conflicted. | 
 |  | 
 |    [ctf_dedup_conflictify_unshared, ctf_dedup_multiple_input_dicts] | 
 |    When linking in CTF_LINK_SHARE_DUPLICATED mode, we would like all types that | 
 |    are used in only one TU to end up in a per-CU dict. The easiest way to do | 
 |    that is to mark them conflicted.  ctf_dedup_conflictify_unshared does this, | 
 |    traversing the output mapping and using ctf_dedup_multiple_input_dicts to | 
 |    check the number of input dicts each distinct type hash value came from: | 
 |    types that only came from one get marked conflicted.  One caveat here is that | 
 |    we need to consider both structs and forwards to them: a struct that appears | 
 |    in one TU and has a dozen citations to an opaque forward in other TUs should | 
 |    *not* be considered to be used in only one TU, because users would find it | 
 |    useful to be able to traverse into opaque structures of that sort: so we use | 
 |    cd_struct_origin to check both structs/unions and the forwards corresponding | 
 |    to them. | 
 |  | 
 |    3) EMISSION. | 
 |  | 
 |    [ctf_dedup_walk_output_mapping, ctf_dedup_rwalk_output_mapping, | 
 |     ctf_dedup_rwalk_one_output_mapping] | 
 |    Emission involves another walk of the entire output mapping, this time | 
 |    traversing everything other than struct members, recursively.  Types are | 
 |    emitted from leaves to trunk, emitting all types a type cites before emitting | 
 |    the type itself.  We sort the output mapping before traversing it, for | 
 |    reproducibility and also correctness: the input dicts may have parent/child | 
 |    relationships, so we simply sort all types that first appear in parents | 
 |    before all children, then sort types that first appear in dicts appearing | 
 |    earlier on the linker command line before those that appear later, then sort | 
 |    by input ctf_id_t.  (This is where we use cd_output_first_gid, collected | 
 |    above.) | 
 |  | 
 |    The walking is done using a recursive traverser which arranges to not revisit | 
 |    any type already visited and to call its callback once per input GID for | 
 |    input GIDs corresponding to conflicted output types.  The traverser only | 
 |    finds input types and calls a callback for them as many times as the output | 
 |    needs to appear: it doesn't try to figure out anything about where the output | 
 |    might go.  That's done by the callback based on whether the type is | 
 |    marked conflicted or not. | 
 |  | 
 |    [ctf_dedup_emit_type, ctf_dedup_id_to_target, ctf_dedup_synthesize_forward] | 
 |    ctf_dedup_emit_type is the (sole) callback for ctf_dedup_walk_output_mapping. | 
 |    Conflicted types have all necessary dictionaries created, and then we emit | 
 |    the type into each dictionary in turn, working over each input CTF type | 
 |    corresponding to each hash value and using ctf_dedup_id_to_target to map each | 
 |    input ctf_id_t into the corresponding type in the output (dealing with input | 
 |    ctf_id_t's with parents in the process by simply chasing to the parent dict | 
 |    if the type we're looking up is in there).  Emitting structures involves | 
 |    simply noting that the members of this structure need emission later on: | 
 |    because you cannot cite a single structure member from another type, we avoid | 
 |    emitting the members at this stage to keep recursion depths down a bit. | 
 |  | 
 |    At this point, if we have by some mischance decided that two different types | 
 |    with child types that hash to different values have in fact got the same hash | 
 |    value themselves and *not* marked it conflicting, the type walk will walk | 
 |    only *one* of them and in all likelihood we'll find that we are trying to | 
 |    emit a type into some child dictionary that references a type that was never | 
 |    emitted into that dictionary and assertion-fail.  This always indicates a bug | 
 |    in the conflictedness marking machinery or the hashing code, or both. | 
 |  | 
 |    ctf_dedup_id_to_target calls ctf_dedup_synthesize_forward to do one extra | 
 |    thing, alluded to above: if this is a conflicted tagged structure or union, | 
 |    and the target is the shared dict (i.e., the type we're being asked to emit | 
 |    is not itself conflicted so can't just point straight at the conflicted | 
 |    type), we instead synthesise a forward with the same name, emit it into the | 
 |    shared dict, record it in cd_output_emission_conflicted_forwards so that we | 
 |    don't re-emit it, and return it.  This means that cycles that contain | 
 |    conflicts do not cause the entire cycle to be replicated in every child: only | 
 |    that piece of the cycle which takes you back as far as the closest tagged | 
 |    struct/union needs to be replicated.  This trick means that no part of the | 
 |    deduplicator needs a cycle detector: every recursive walk can stop at tagged | 
 |    structures. | 
 |  | 
 |    [ctf_dedup_emit_struct_members] | 
 |    The final stage of emission is to walk over all structures with members | 
 |    that need emission and emit all of them. Every type has been emitted at | 
 |    this stage, so emission cannot fail. | 
 |  | 
 |    [ctf_dedup_populate_type_mappings, ctf_dedup_populate_type_mapping] | 
 |    Finally, we update the input -> output type ID mappings used by the ctf-link | 
 |    machinery to update all the other sections.  This is surprisingly expensive | 
 |    and may be replaced with a scheme which lets the ctf-link machinery extract | 
 |    the needed info directly from the deduplicator.  */ | 
 |  | 
 | /* Possible future optimizations are flagged with 'optimization opportunity' | 
 |    below.  */ | 
 |  | 
 | /* Global optimization opportunity: a GC pass, eliminating types with no direct | 
 |    or indirect citations from the other sections in the dictionary.  */ | 
 |  | 
 | /* Internal flag values for ctf_dedup_hash_type.  */ | 
 |  | 
 | /* Child call: consider forwardable types equivalent to forwards or stubs below | 
 |    this point.  */ | 
 | #define CTF_DEDUP_HASH_INTERNAL_CHILD         0x01 | 
 |  | 
 | /* Transform references to single ctf_id_ts in passed-in inputs into a number | 
 |    that will fit in a uint64_t.  Needs rethinking if CTF_MAX_TYPE is boosted. | 
 |  | 
 |    On 32-bit platforms, we pack things together differently: see the note | 
 |    above.  */ | 
 |  | 
 | #if UINTPTR_MAX < UINT64_MAX | 
 | # define IDS_NEED_ALLOCATION 1 | 
 | # define CTF_DEDUP_GID(fp, input, type) id_to_packed_id (fp, input, type) | 
 | # define CTF_DEDUP_GID_TO_INPUT(id) packed_id_to_input (id) | 
 | # define CTF_DEDUP_GID_TO_TYPE(id) packed_id_to_type (id) | 
 | #else | 
 | # define CTF_DEDUP_GID(fp, input, type)	\ | 
 |   (void *) (((uint64_t) input) << 32 | (type)) | 
 | # define CTF_DEDUP_GID_TO_INPUT(id) ((int) (((uint64_t) id) >> 32)) | 
 | # define CTF_DEDUP_GID_TO_TYPE(id) (ctf_id_t) (((uint64_t) id) & ~(0xffffffff00000000ULL)) | 
 | #endif | 
 |  | 
 | #ifdef IDS_NEED_ALLOCATION | 
 |  | 
 |  /* This is the 32-bit path, which stores GIDs in a pool and returns a pointer | 
 |     into the pool.  It is notably less efficient than the 64-bit direct storage | 
 |     approach, but with a smaller key, this is all we can do.  */ | 
 |  | 
 | static void * | 
 | id_to_packed_id (ctf_dict_t *fp, int input_num, ctf_id_t type) | 
 | { | 
 |   const void *lookup; | 
 |   ctf_type_id_key_t *dynkey = NULL; | 
 |   ctf_type_id_key_t key = { input_num, type }; | 
 |  | 
 |   if (!ctf_dynhash_lookup_kv (fp->ctf_dedup.cd_id_to_dict_t, | 
 | 			      &key, &lookup, NULL)) | 
 |     { | 
 |       if ((dynkey = malloc (sizeof (ctf_type_id_key_t))) == NULL) | 
 | 	goto oom; | 
 |       memcpy (dynkey, &key, sizeof (ctf_type_id_key_t)); | 
 |  | 
 |       if (ctf_dynhash_insert (fp->ctf_dedup.cd_id_to_dict_t, dynkey, NULL) < 0) | 
 | 	goto oom; | 
 |  | 
 |       ctf_dynhash_lookup_kv (fp->ctf_dedup.cd_id_to_dict_t, | 
 | 			     dynkey, &lookup, NULL); | 
 |     } | 
 |   /* We use a raw assert() here because there isn't really a way to get any sort | 
 |      of error back from this routine without vastly complicating things for the | 
 |      much more common case of !IDS_NEED_ALLOCATION.  */ | 
 |   assert (lookup); | 
 |   return (void *) lookup; | 
 |  | 
 |  oom: | 
 |   free (dynkey); | 
 |   ctf_set_errno (fp, ENOMEM); | 
 |   return NULL; | 
 | } | 
 |  | 
 | static int | 
 | packed_id_to_input (const void *id) | 
 | { | 
 |   const ctf_type_id_key_t *key = (ctf_type_id_key_t *) id; | 
 |  | 
 |   return key->ctii_input_num; | 
 | } | 
 |  | 
 | static ctf_id_t | 
 | packed_id_to_type (const void *id) | 
 | { | 
 |   const ctf_type_id_key_t *key = (ctf_type_id_key_t *) id; | 
 |  | 
 |   return key->ctii_type; | 
 | } | 
 | #endif | 
 |  | 
 | /* Make an element in a dynhash-of-dynsets, or return it if already present.  */ | 
 |  | 
 | static ctf_dynset_t * | 
 | make_set_element (ctf_dynhash_t *set, const void *key) | 
 | { | 
 |   ctf_dynset_t *element; | 
 |  | 
 |   if ((element = ctf_dynhash_lookup (set, key)) == NULL) | 
 |     { | 
 |       if ((element = ctf_dynset_create (htab_hash_string, | 
 | 					htab_eq_string, | 
 | 					NULL)) == NULL) | 
 | 	return NULL; | 
 |  | 
 |       if (ctf_dynhash_insert (set, (void *) key, element) < 0) | 
 | 	{ | 
 | 	  ctf_dynset_destroy (element); | 
 | 	  return NULL; | 
 | 	} | 
 |     } | 
 |  | 
 |   return element; | 
 | } | 
 |  | 
 | /* Initialize the dedup atoms table.  */ | 
 | int | 
 | ctf_dedup_atoms_init (ctf_dict_t *fp) | 
 | { | 
 |   if (fp->ctf_dedup_atoms) | 
 |     return 0; | 
 |  | 
 |   if (!fp->ctf_dedup_atoms_alloc) | 
 |     { | 
 |       if ((fp->ctf_dedup_atoms_alloc | 
 | 	   = ctf_dynset_create (htab_hash_string, htab_eq_string, | 
 | 				free)) == NULL) | 
 | 	return ctf_set_errno (fp, ENOMEM); | 
 |     } | 
 |   fp->ctf_dedup_atoms = fp->ctf_dedup_atoms_alloc; | 
 |   return 0; | 
 | } | 
 |  | 
 | /* Intern things in the dedup atoms table.  */ | 
 |  | 
 | static const char * | 
 | intern (ctf_dict_t *fp, char *atom) | 
 | { | 
 |   const void *foo; | 
 |  | 
 |   if (atom == NULL) | 
 |     return NULL; | 
 |  | 
 |   if (!ctf_dynset_exists (fp->ctf_dedup_atoms, atom, &foo)) | 
 |     { | 
 |       if (ctf_dynset_insert (fp->ctf_dedup_atoms, atom) < 0) | 
 | 	{ | 
 | 	  ctf_set_errno (fp, ENOMEM); | 
 | 	  return NULL; | 
 | 	} | 
 |       foo = atom; | 
 |     } | 
 |   else | 
 |     free (atom); | 
 |  | 
 |   return (const char *) foo; | 
 | } | 
 |  | 
 | /* Add an indication of the namespace to a type name in a way that is not valid | 
 |    for C identifiers.  Used to maintain hashes of type names to other things | 
 |    while allowing for the four C namespaces (normal, struct, union, enum). | 
 |    Return a new dynamically-allocated string.  */ | 
 | static const char * | 
 | ctf_decorate_type_name (ctf_dict_t *fp, const char *name, int kind) | 
 | { | 
 |   ctf_dedup_t *d = &fp->ctf_dedup; | 
 |   const char *ret; | 
 |   const char *k; | 
 |   char *p; | 
 |   size_t i; | 
 |  | 
 |   switch (kind) | 
 |     { | 
 |     case CTF_K_STRUCT: | 
 |       k = "s "; | 
 |       i = 0; | 
 |       break; | 
 |     case CTF_K_UNION: | 
 |       k = "u "; | 
 |       i = 1; | 
 |       break; | 
 |     case CTF_K_ENUM: | 
 |       k = "e "; | 
 |       i = 2; | 
 |       break; | 
 |     default: | 
 |       k = ""; | 
 |       i = 3; | 
 |     } | 
 |  | 
 |   if ((ret = ctf_dynhash_lookup (d->cd_decorated_names[i], name)) == NULL) | 
 |     { | 
 |       char *str; | 
 |  | 
 |       if ((str = malloc (strlen (name) + strlen (k) + 1)) == NULL) | 
 | 	goto oom; | 
 |  | 
 |       p = stpcpy (str, k); | 
 |       strcpy (p, name); | 
 |       ret = intern (fp, str); | 
 |       if (!ret) | 
 | 	goto oom; | 
 |  | 
 |       if (ctf_dynhash_cinsert (d->cd_decorated_names[i], name, ret) < 0) | 
 | 	goto oom; | 
 |     } | 
 |  | 
 |   return ret; | 
 |  | 
 |  oom: | 
 |   ctf_set_errno (fp, ENOMEM); | 
 |   return NULL; | 
 | } | 
 |  | 
 | /* Hash a type, possibly debugging-dumping something about it as well.  */ | 
 | static inline void | 
 | ctf_dedup_sha1_add (ctf_sha1_t *sha1, const void *buf, size_t len, | 
 | 		    const char *description _libctf_unused_, | 
 | 		    unsigned long depth _libctf_unused_) | 
 | { | 
 |   ctf_sha1_add (sha1, buf, len); | 
 |  | 
 | #ifdef ENABLE_LIBCTF_HASH_DEBUGGING | 
 |   ctf_sha1_t tmp; | 
 |   char tmp_hval[CTF_SHA1_SIZE]; | 
 |   tmp = *sha1; | 
 |   ctf_sha1_fini (&tmp, tmp_hval); | 
 |   ctf_dprintf ("%lu: after hash addition of %s: %s\n", depth, description, | 
 | 	       tmp_hval); | 
 | #endif | 
 | } | 
 |  | 
 | static const char * | 
 | ctf_dedup_hash_type (ctf_dict_t *fp, ctf_dict_t *input, | 
 | 		     ctf_dict_t **inputs, uint32_t *parents, | 
 | 		     int input_num, ctf_id_t type, int flags, | 
 | 		     unsigned long depth, | 
 | 		     int (*populate_fun) (ctf_dict_t *fp, | 
 | 					  ctf_dict_t *input, | 
 | 					  ctf_dict_t **inputs, | 
 | 					  int input_num, | 
 | 					  ctf_id_t type, | 
 | 					  void *id, | 
 | 					  const char *decorated_name, | 
 | 					  const char *hash)); | 
 |  | 
 | /* Determine whether this type is being hashed as a stub (in which case it is | 
 |    unsafe to cache it).  */ | 
 | static int | 
 | ctf_dedup_is_stub (const char *name, int kind, int fwdkind, int flags) | 
 | { | 
 |   /* We can cache all types unless we are recursing to children and are hashing | 
 |      in a tagged struct, union or forward, all of which are replaced with their | 
 |      decorated name as a stub and will have different hash values when hashed at | 
 |      the top level.  */ | 
 |  | 
 |   return ((flags & CTF_DEDUP_HASH_INTERNAL_CHILD) && name | 
 | 	  && (kind == CTF_K_STRUCT || kind == CTF_K_UNION | 
 | 	      || (kind == CTF_K_FORWARD && (fwdkind == CTF_K_STRUCT | 
 | 					    || fwdkind == CTF_K_UNION)))); | 
 | } | 
 |  | 
 | /* Populate struct_origin if need be (not already populated, or populated with | 
 |    a different origin), in which case it must go to -1, "shared".) | 
 |  | 
 |    Only called for forwards or forwardable types with names, when the link mode | 
 |    is CTF_LINK_SHARE_DUPLICATED.  */ | 
 | static int | 
 | ctf_dedup_record_origin (ctf_dict_t *fp, int input_num, const char *decorated, | 
 | 			 void *id) | 
 | { | 
 |   ctf_dedup_t *d = &fp->ctf_dedup; | 
 |   void *origin; | 
 |   int populate_origin = 0; | 
 |  | 
 |   if (ctf_dynhash_lookup_kv (d->cd_struct_origin, decorated, NULL, &origin)) | 
 |     { | 
 |       if (CTF_DEDUP_GID_TO_INPUT (origin) != input_num | 
 | 	  && CTF_DEDUP_GID_TO_INPUT (origin) != -1) | 
 | 	{ | 
 | 	  populate_origin = 1; | 
 | 	  origin = CTF_DEDUP_GID (fp, -1, -1); | 
 | 	} | 
 |     } | 
 |   else | 
 |     { | 
 |       populate_origin = 1; | 
 |       origin = id; | 
 |     } | 
 |  | 
 |   if (populate_origin) | 
 |     if (ctf_dynhash_cinsert (d->cd_struct_origin, decorated, origin) < 0) | 
 |       return ctf_set_errno (fp, errno); | 
 |   return 0; | 
 | } | 
 |  | 
 | /* Do the underlying hashing and recursion for ctf_dedup_hash_type (which it | 
 |    calls, recursively).  */ | 
 |  | 
 | static const char * | 
 | ctf_dedup_rhash_type (ctf_dict_t *fp, ctf_dict_t *input, ctf_dict_t **inputs, | 
 | 		      uint32_t *parents, int input_num, ctf_id_t type, | 
 | 		      void *type_id, const ctf_type_t *tp, const char *name, | 
 | 		      const char *decorated, int kind, int flags, | 
 | 		      unsigned long depth, | 
 | 		      int (*populate_fun) (ctf_dict_t *fp, | 
 | 					   ctf_dict_t *input, | 
 | 					   ctf_dict_t **inputs, | 
 | 					   int input_num, | 
 | 					   ctf_id_t type, | 
 | 					   void *id, | 
 | 					   const char *decorated_name, | 
 | 					   const char *hash)) | 
 | { | 
 |   ctf_dedup_t *d = &fp->ctf_dedup; | 
 |   ctf_next_t *i = NULL; | 
 |   ctf_sha1_t hash; | 
 |   ctf_id_t child_type; | 
 |   char hashbuf[CTF_SHA1_SIZE]; | 
 |   const char *hval = NULL; | 
 |   const char *whaterr; | 
 |   int err = 0; | 
 |  | 
 |   const char *citer = NULL; | 
 |   ctf_dynset_t *citers = NULL; | 
 |  | 
 |   /* Add a citer to the citers set.  */ | 
 | #define ADD_CITER(citers, hval)						\ | 
 |   do									\ | 
 |     {									\ | 
 |       whaterr = N_("error updating citers");				\ | 
 |       if (!citers)							\ | 
 | 	if ((citers = ctf_dynset_create (htab_hash_string,		\ | 
 | 					 htab_eq_string,		\ | 
 | 					 NULL)) == NULL)		\ | 
 | 	  goto oom;							\ | 
 |       if (ctf_dynset_cinsert (citers, hval) < 0)			\ | 
 | 	goto oom;							\ | 
 |     }									\ | 
 |   while (0) | 
 |  | 
 |   /* If this is a named struct or union or a forward to one, and this is a child | 
 |      traversal, treat this type as if it were a forward -- do not recurse to | 
 |      children, ignore all content not already hashed in, and hash in the | 
 |      decorated name of the type instead.  */ | 
 |  | 
 |   if (ctf_dedup_is_stub (name, kind, tp->ctt_type, flags)) | 
 |     { | 
 | #ifdef ENABLE_LIBCTF_HASH_DEBUGGING | 
 |       ctf_dprintf ("Struct/union/forward citation: substituting forwarding " | 
 | 		   "stub with decorated name %s\n", decorated); | 
 |  | 
 | #endif | 
 |       ctf_sha1_init (&hash); | 
 |       ctf_dedup_sha1_add (&hash, decorated, strlen (decorated) + 1, | 
 | 			  "decorated struct/union/forward name", depth); | 
 |       ctf_sha1_fini (&hash, hashbuf); | 
 |  | 
 |       if ((hval = intern (fp, strdup (hashbuf))) == NULL) | 
 | 	{ | 
 | 	  ctf_err_warn (fp, 0, 0, _("%s (%i): out of memory during forwarding-" | 
 | 				    "stub hashing for type with GID %p"), | 
 | 			ctf_link_input_name (input), input_num, type_id); | 
 | 	  return NULL;				/* errno is set for us.  */ | 
 | 	} | 
 |  | 
 |       /* In share-duplicated link mode, make sure the origin of this type is | 
 | 	 recorded, even if this is a type in a parent dict which will not be | 
 | 	 directly traversed.  */ | 
 |       if (d->cd_link_flags & CTF_LINK_SHARE_DUPLICATED | 
 | 	  && ctf_dedup_record_origin (fp, input_num, decorated, type_id) < 0) | 
 | 	return NULL;				/* errno is set for us.  */ | 
 |  | 
 |       return hval; | 
 |     } | 
 |  | 
 |   /* Now ensure that subsequent recursive calls (but *not* the top-level call) | 
 |      get this treatment.  */ | 
 |   flags |= CTF_DEDUP_HASH_INTERNAL_CHILD; | 
 |  | 
 |   /* If this is a struct, union, or forward with a name, record the unique | 
 |      originating input TU, if there is one.  */ | 
 |  | 
 |   if (decorated && (ctf_forwardable_kind (kind) || kind != CTF_K_FORWARD)) | 
 |     if (d->cd_link_flags & CTF_LINK_SHARE_DUPLICATED | 
 | 	&& ctf_dedup_record_origin (fp, input_num, decorated, type_id) < 0) | 
 |       return NULL;				/* errno is set for us.  */ | 
 |  | 
 | #ifdef ENABLE_LIBCTF_HASH_DEBUGGING | 
 |   ctf_dprintf ("%lu: hashing thing with ID %i/%lx (kind %i): %s.\n", | 
 | 	       depth, input_num, type, kind, name ? name : ""); | 
 | #endif | 
 |  | 
 |   /* Some type kinds don't have names: the API provides no way to set the name, | 
 |      so the type the deduplicator outputs will be nameless even if the input | 
 |      somehow has a name, and the name should not be mixed into the hash.  */ | 
 |  | 
 |   switch (kind) | 
 |     { | 
 |     case CTF_K_POINTER: | 
 |     case CTF_K_ARRAY: | 
 |     case CTF_K_FUNCTION: | 
 |     case CTF_K_VOLATILE: | 
 |     case CTF_K_CONST: | 
 |     case CTF_K_RESTRICT: | 
 |     case CTF_K_SLICE: | 
 |       name = NULL; | 
 |     } | 
 |  | 
 |   /* Mix in invariant stuff, transforming the type kind if needed.  Note that | 
 |      the vlen is *not* hashed in: the actual variable-length info is hashed in | 
 |      instead, piecewise.  The vlen is not part of the type, only the | 
 |      variable-length data is: identical types with distinct vlens are quite | 
 |      possible.  Equally, we do not want to hash in the isroot flag: both the | 
 |      compiler and the deduplicator set the nonroot flag to indicate clashes with | 
 |      *other types in the same TU* with the same name: so two types can easily | 
 |      have distinct nonroot flags, yet be exactly the same type.*/ | 
 |  | 
 |   ctf_sha1_init (&hash); | 
 |   if (name) | 
 |     ctf_dedup_sha1_add (&hash, name, strlen (name) + 1, "name", depth); | 
 |   ctf_dedup_sha1_add (&hash, &kind, sizeof (uint32_t), "kind", depth); | 
 |  | 
 |   /* Hash content of this type.  */ | 
 |   switch (kind) | 
 |     { | 
 |     case CTF_K_UNKNOWN: | 
 |       /* No extra state.  */ | 
 |       break; | 
 |     case CTF_K_FORWARD: | 
 |  | 
 |       /* Add the forwarded kind, stored in the ctt_type.  */ | 
 |       ctf_dedup_sha1_add (&hash, &tp->ctt_type, sizeof (tp->ctt_type), | 
 | 			  "forwarded kind", depth); | 
 |       break; | 
 |     case CTF_K_INTEGER: | 
 |     case CTF_K_FLOAT: | 
 |       { | 
 | 	ctf_encoding_t ep; | 
 | 	memset (&ep, 0, sizeof (ctf_encoding_t)); | 
 |  | 
 | 	ctf_dedup_sha1_add (&hash, &tp->ctt_size, sizeof (uint32_t), "size", | 
 | 			    depth); | 
 | 	if (ctf_type_encoding (input, type, &ep) < 0) | 
 | 	  { | 
 | 	    whaterr = N_("error getting encoding"); | 
 | 	    goto input_err; | 
 | 	  } | 
 | 	ctf_dedup_sha1_add (&hash, &ep, sizeof (ctf_encoding_t), "encoding", | 
 | 			    depth); | 
 | 	break; | 
 |       } | 
 |       /* Types that reference other types.  */ | 
 |     case CTF_K_TYPEDEF: | 
 |     case CTF_K_VOLATILE: | 
 |     case CTF_K_CONST: | 
 |     case CTF_K_RESTRICT: | 
 |     case CTF_K_POINTER: | 
 |       /* Hash the referenced type, if not already hashed, and mix it in.  */ | 
 |       child_type = ctf_type_reference (input, type); | 
 |       if ((hval = ctf_dedup_hash_type (fp, input, inputs, parents, input_num, | 
 | 				       child_type, flags, depth, | 
 | 				       populate_fun)) == NULL) | 
 | 	{ | 
 | 	  whaterr = N_("error doing referenced type hashing"); | 
 | 	  goto err; | 
 | 	} | 
 |       ctf_dedup_sha1_add (&hash, hval, strlen (hval) + 1, "referenced type", | 
 | 			  depth); | 
 |       citer = hval; | 
 |  | 
 |       break; | 
 |  | 
 |       /* The slices of two types hash identically only if the type they overlay | 
 | 	 also has the same encoding.  This is not ideal, but in practice will work | 
 | 	 well enough.  We work directly rather than using the CTF API because | 
 | 	 we do not want the slice's normal automatically-shine-through | 
 | 	 semantics to kick in here.  */ | 
 |     case CTF_K_SLICE: | 
 |       { | 
 | 	const ctf_slice_t *slice; | 
 | 	const ctf_dtdef_t *dtd; | 
 | 	ssize_t size; | 
 | 	ssize_t increment; | 
 |  | 
 | 	child_type = ctf_type_reference (input, type); | 
 | 	ctf_get_ctt_size (input, tp, &size, &increment); | 
 | 	ctf_dedup_sha1_add (&hash, &size, sizeof (ssize_t), "size", depth); | 
 |  | 
 | 	if ((hval = ctf_dedup_hash_type (fp, input, inputs, parents, input_num, | 
 | 					 child_type, flags, depth, | 
 | 					 populate_fun)) == NULL) | 
 | 	  { | 
 | 	    whaterr = N_("error doing slice-referenced type hashing"); | 
 | 	    goto err; | 
 | 	  } | 
 | 	ctf_dedup_sha1_add (&hash, hval, strlen (hval) + 1, "sliced type", | 
 | 			    depth); | 
 | 	citer = hval; | 
 |  | 
 | 	if ((dtd = ctf_dynamic_type (input, type)) != NULL) | 
 | 	  slice = (ctf_slice_t *) dtd->dtd_vlen; | 
 | 	else | 
 | 	  slice = (ctf_slice_t *) ((uintptr_t) tp + increment); | 
 |  | 
 | 	ctf_dedup_sha1_add (&hash, &slice->cts_offset, | 
 | 			    sizeof (slice->cts_offset), "slice offset", depth); | 
 | 	ctf_dedup_sha1_add (&hash, &slice->cts_bits, | 
 | 			    sizeof (slice->cts_bits), "slice bits", depth); | 
 | 	break; | 
 |       } | 
 |  | 
 |     case CTF_K_ARRAY: | 
 |       { | 
 | 	ctf_arinfo_t ar; | 
 |  | 
 | 	if (ctf_array_info (input, type, &ar) < 0) | 
 | 	  { | 
 | 	    whaterr = N_("error getting array info"); | 
 | 	    goto input_err; | 
 | 	  } | 
 |  | 
 | 	if ((hval = ctf_dedup_hash_type (fp, input, inputs, parents, input_num, | 
 | 					 ar.ctr_contents, flags, depth, | 
 | 					 populate_fun)) == NULL) | 
 | 	  { | 
 | 	    whaterr = N_("error doing array contents type hashing"); | 
 | 	    goto err; | 
 | 	  } | 
 | 	ctf_dedup_sha1_add (&hash, hval, strlen (hval) + 1, "array contents", | 
 | 			    depth); | 
 | 	ADD_CITER (citers, hval); | 
 |  | 
 | 	if ((hval = ctf_dedup_hash_type (fp, input, inputs, parents, input_num, | 
 | 					 ar.ctr_index, flags, depth, | 
 | 					 populate_fun)) == NULL) | 
 | 	  { | 
 | 	    whaterr = N_("error doing array index type hashing"); | 
 | 	    goto err; | 
 | 	  } | 
 | 	ctf_dedup_sha1_add (&hash, hval, strlen (hval) + 1, "array index", | 
 | 			    depth); | 
 | 	ctf_dedup_sha1_add (&hash, &ar.ctr_nelems, sizeof (ar.ctr_nelems), | 
 | 			    "element count", depth); | 
 | 	ADD_CITER (citers, hval); | 
 |  | 
 | 	break; | 
 |       } | 
 |     case CTF_K_FUNCTION: | 
 |       { | 
 | 	ctf_funcinfo_t fi; | 
 | 	ctf_id_t *args; | 
 | 	uint32_t j; | 
 |  | 
 | 	if (ctf_func_type_info (input, type, &fi) < 0) | 
 | 	  { | 
 | 	    whaterr = N_("error getting func type info"); | 
 | 	    goto input_err; | 
 | 	  } | 
 |  | 
 | 	if ((hval = ctf_dedup_hash_type (fp, input, inputs, parents, input_num, | 
 | 					 fi.ctc_return, flags, depth, | 
 | 					 populate_fun)) == NULL) | 
 | 	  { | 
 | 	    whaterr = N_("error getting func return type"); | 
 | 	    goto err; | 
 | 	  } | 
 | 	ctf_dedup_sha1_add (&hash, hval, strlen (hval) + 1, "func return", | 
 | 			    depth); | 
 | 	ctf_dedup_sha1_add (&hash, &fi.ctc_argc, sizeof (fi.ctc_argc), | 
 | 			    "func argc", depth); | 
 | 	ctf_dedup_sha1_add (&hash, &fi.ctc_flags, sizeof (fi.ctc_flags), | 
 | 			    "func flags", depth); | 
 | 	ADD_CITER (citers, hval); | 
 |  | 
 | 	if ((args = calloc (fi.ctc_argc, sizeof (ctf_id_t))) == NULL) | 
 | 	  { | 
 | 	    err = ENOMEM; | 
 | 	    whaterr = N_("error doing memory allocation"); | 
 | 	    goto err; | 
 | 	  } | 
 |  | 
 | 	if (ctf_func_type_args (input, type, fi.ctc_argc, args) < 0) | 
 | 	  { | 
 | 	    free (args); | 
 | 	    whaterr = N_("error getting func arg type"); | 
 | 	    goto input_err; | 
 | 	  } | 
 | 	for (j = 0; j < fi.ctc_argc; j++) | 
 | 	  { | 
 | 	    if ((hval = ctf_dedup_hash_type (fp, input, inputs, parents, | 
 | 					     input_num, args[j], flags, depth, | 
 | 					     populate_fun)) == NULL) | 
 | 	      { | 
 | 		free (args); | 
 | 		whaterr = N_("error doing func arg type hashing"); | 
 | 		goto err; | 
 | 	      } | 
 | 	    ctf_dedup_sha1_add (&hash, hval, strlen (hval) + 1, "func arg type", | 
 | 				depth); | 
 | 	    ADD_CITER (citers, hval); | 
 | 	  } | 
 | 	free (args); | 
 | 	break; | 
 |       } | 
 |     case CTF_K_ENUM: | 
 |       { | 
 | 	int val; | 
 | 	const char *ename; | 
 |  | 
 | 	ctf_dedup_sha1_add (&hash, &tp->ctt_size, sizeof (uint32_t), | 
 | 			    "enum size", depth); | 
 | 	while ((ename = ctf_enum_next (input, type, &i, &val)) != NULL) | 
 | 	  { | 
 | 	    ctf_dedup_sha1_add (&hash, ename, strlen (ename) + 1, "enumerator", | 
 | 				depth); | 
 | 	    ctf_dedup_sha1_add (&hash, &val, sizeof (val), "enumerand", depth); | 
 | 	  } | 
 | 	if (ctf_errno (input) != ECTF_NEXT_END) | 
 | 	  { | 
 | 	    whaterr = N_("error doing enum member iteration"); | 
 | 	    goto input_err; | 
 | 	  } | 
 | 	break; | 
 |       } | 
 |     /* Top-level only.  */ | 
 |     case CTF_K_STRUCT: | 
 |     case CTF_K_UNION: | 
 |       { | 
 | 	ssize_t offset; | 
 | 	const char *mname; | 
 | 	ctf_id_t membtype; | 
 | 	ssize_t size; | 
 |  | 
 | 	ctf_get_ctt_size (input, tp, &size, NULL); | 
 | 	ctf_dedup_sha1_add (&hash, &size, sizeof (ssize_t), "struct size", | 
 | 			    depth); | 
 |  | 
 | 	while ((offset = ctf_member_next (input, type, &i, &mname, &membtype, | 
 | 					  0)) >= 0) | 
 | 	  { | 
 | 	    if (mname == NULL) | 
 | 	      mname = ""; | 
 | 	    ctf_dedup_sha1_add (&hash, mname, strlen (mname) + 1, | 
 | 				"member name", depth); | 
 |  | 
 | #ifdef ENABLE_LIBCTF_HASH_DEBUGGING | 
 | 	    ctf_dprintf ("%lu: Traversing to member %s\n", depth, mname); | 
 | #endif | 
 | 	    if ((hval = ctf_dedup_hash_type (fp, input, inputs, parents, | 
 | 					     input_num, membtype, flags, depth, | 
 | 					     populate_fun)) == NULL) | 
 | 	      { | 
 | 		whaterr = N_("error doing struct/union member type hashing"); | 
 | 		goto iterr; | 
 | 	      } | 
 |  | 
 | 	    ctf_dedup_sha1_add (&hash, hval, strlen (hval) + 1, "member hash", | 
 | 				depth); | 
 | 	    ctf_dedup_sha1_add (&hash, &offset, sizeof (offset), "member offset", | 
 | 				depth); | 
 | 	    ADD_CITER (citers, hval); | 
 | 	  } | 
 | 	if (ctf_errno (input) != ECTF_NEXT_END) | 
 | 	  { | 
 | 	    whaterr = N_("error doing struct/union member iteration"); | 
 | 	    goto input_err; | 
 | 	  } | 
 | 	break; | 
 |       } | 
 |     default: | 
 |       whaterr = N_("error: unknown type kind"); | 
 |       goto err; | 
 |     } | 
 |   ctf_sha1_fini (&hash, hashbuf); | 
 |  | 
 |   if ((hval = intern (fp, strdup (hashbuf))) == NULL) | 
 |     { | 
 |       whaterr = N_("cannot intern hash"); | 
 |       goto oom; | 
 |     } | 
 |  | 
 |   /* Populate the citers for this type's subtypes, now the hash for the type | 
 |      itself is known.  */ | 
 |   whaterr = N_("error tracking citers"); | 
 |  | 
 |   if (citer) | 
 |     { | 
 |       ctf_dynset_t *citer_hashes; | 
 |  | 
 |       if ((citer_hashes = make_set_element (d->cd_citers, citer)) == NULL) | 
 | 	goto oom; | 
 |       if (ctf_dynset_cinsert (citer_hashes, hval) < 0) | 
 | 	goto oom; | 
 |     } | 
 |   else if (citers) | 
 |     { | 
 |       const void *k; | 
 |  | 
 |       while ((err = ctf_dynset_cnext (citers, &i, &k)) == 0) | 
 | 	{ | 
 | 	  ctf_dynset_t *citer_hashes; | 
 | 	  citer = (const char *) k; | 
 |  | 
 | 	  if ((citer_hashes = make_set_element (d->cd_citers, citer)) == NULL) | 
 | 	    goto oom; | 
 |  | 
 | 	  if (ctf_dynset_exists (citer_hashes, hval, NULL)) | 
 | 	    continue; | 
 | 	  if (ctf_dynset_cinsert (citer_hashes, hval) < 0) | 
 | 	    goto oom; | 
 | 	} | 
 |       if (err != ECTF_NEXT_END) | 
 | 	goto err; | 
 |       ctf_dynset_destroy (citers); | 
 |     } | 
 |  | 
 |   return hval; | 
 |  | 
 |  iterr: | 
 |   ctf_next_destroy (i); | 
 |  input_err: | 
 |   err = ctf_errno (input); | 
 |  err: | 
 |   ctf_sha1_fini (&hash, NULL); | 
 |   ctf_err_warn (fp, 0, err, _("%s (%i): %s: during type hashing for type %lx, " | 
 | 			      "kind %i"), ctf_link_input_name (input), | 
 | 		input_num, gettext (whaterr), type, kind); | 
 |   return NULL; | 
 |  oom: | 
 |   ctf_set_errno (fp, errno); | 
 |   ctf_err_warn (fp, 0, 0, _("%s (%i): %s: during type hashing for type %lx, " | 
 | 			    "kind %i"), ctf_link_input_name (input), | 
 | 		input_num, gettext (whaterr), type, kind); | 
 |   return NULL; | 
 | } | 
 |  | 
 | /* Hash a TYPE in the INPUT: FP is the eventual output, where the ctf_dedup | 
 |    state is stored.  INPUT_NUM is the number of this input in the set of inputs. | 
 |    Record its hash in FP's cd_type_hashes once it is known.  PARENTS is | 
 |    described in the comment above ctf_dedup. | 
 |  | 
 |    (The flags argument currently accepts only the flag | 
 |    CTF_DEDUP_HASH_INTERNAL_CHILD, an implementation detail used to prevent | 
 |    struct/union hashing in recursive traversals below the TYPE.) | 
 |  | 
 |    We use the CTF API rather than direct access wherever possible, because types | 
 |    that appear identical through the API should be considered identical, with | 
 |    one exception: slices should only be considered identical to other slices, | 
 |    not to the corresponding unsliced type. | 
 |  | 
 |    The POPULATE_FUN is a mandatory hook that populates other mappings with each | 
 |    type we see (excepting types that are recursively hashed as stubs).  The | 
 |    caller should not rely on the order of calls to this hook, though it will be | 
 |    called at least once for every non-stub reference to every type. | 
 |  | 
 |    Returns a hash value (an atom), or NULL on error.  */ | 
 |  | 
 | static const char * | 
 | ctf_dedup_hash_type (ctf_dict_t *fp, ctf_dict_t *input, | 
 | 		     ctf_dict_t **inputs, uint32_t *parents, | 
 | 		     int input_num, ctf_id_t type, int flags, | 
 | 		     unsigned long depth, | 
 | 		     int (*populate_fun) (ctf_dict_t *fp, | 
 | 					  ctf_dict_t *input, | 
 | 					  ctf_dict_t **inputs, | 
 | 					  int input_num, | 
 | 					  ctf_id_t type, | 
 | 					  void *id, | 
 | 					  const char *decorated_name, | 
 | 					  const char *hash)) | 
 | { | 
 |   ctf_dedup_t *d = &fp->ctf_dedup; | 
 |   const ctf_type_t *tp; | 
 |   void *type_id; | 
 |   const char *hval = NULL; | 
 |   const char *name; | 
 |   const char *whaterr; | 
 |   const char *decorated = NULL; | 
 |   uint32_t kind, fwdkind; | 
 |  | 
 |   depth++; | 
 |  | 
 | #ifdef ENABLE_LIBCTF_HASH_DEBUGGING | 
 |   ctf_dprintf ("%lu: ctf_dedup_hash_type (%i, %lx, flags %x)\n", depth, input_num, type, flags); | 
 | #endif | 
 |  | 
 |   /* The unimplemented type doesn't really exist, but must be noted in parent | 
 |      hashes: so it gets a fixed, arbitrary hash.  */ | 
 |   if (type == 0) | 
 |     return "00000000000000000000"; | 
 |  | 
 |   /* Possible optimization: if the input type is in the parent type space, just | 
 |      copy recursively-cited hashes from the parent's types into the output | 
 |      mapping rather than rehashing them.  */ | 
 |  | 
 |   type_id = CTF_DEDUP_GID (fp, input_num, type); | 
 |  | 
 |   if ((tp = ctf_lookup_by_id (&input, type)) == NULL) | 
 |     { | 
 |       ctf_set_errno (fp, ctf_errno (input)); | 
 |       ctf_err_warn (fp, 0, 0, _("%s (%i): lookup failure for type %lx: " | 
 | 				"flags %x"), ctf_link_input_name (input), | 
 | 		    input_num, type, flags); | 
 |       return NULL;		/* errno is set for us.  */ | 
 |     } | 
 |  | 
 |   kind = LCTF_INFO_KIND (input, tp->ctt_info); | 
 |   name = ctf_strraw (input, tp->ctt_name); | 
 |  | 
 |   if (tp->ctt_name == 0 || !name || name[0] == '\0') | 
 |     name = NULL; | 
 |  | 
 |   /* Decorate the name appropriately for the namespace it appears in: forwards | 
 |      appear in the namespace of their referent.  */ | 
 |  | 
 |   fwdkind = kind; | 
 |   if (name) | 
 |     { | 
 |       if (kind == CTF_K_FORWARD) | 
 | 	fwdkind = tp->ctt_type; | 
 |  | 
 |       if ((decorated = ctf_decorate_type_name (fp, name, fwdkind)) == NULL) | 
 | 	return NULL;				/* errno is set for us.  */ | 
 |     } | 
 |  | 
 |   /* If not hashing a stub, we can rely on various sorts of caches. | 
 |  | 
 |      Optimization opportunity: we may be able to avoid calling the populate_fun | 
 |      sometimes here.  */ | 
 |  | 
 |   if (!ctf_dedup_is_stub (name, kind, fwdkind, flags)) | 
 |     { | 
 |       if ((hval = ctf_dynhash_lookup (d->cd_type_hashes, type_id)) != NULL) | 
 | 	{ | 
 | #ifdef ENABLE_LIBCTF_HASH_DEBUGGING | 
 | 	  ctf_dprintf ("%lu: Known hash for ID %i/%lx: %s\n", depth, input_num, | 
 | 		       type,  hval); | 
 | #endif | 
 | 	  populate_fun (fp, input, inputs, input_num, type, type_id, | 
 | 			decorated, hval); | 
 |  | 
 | 	  return hval; | 
 | 	} | 
 |     } | 
 |  | 
 |   /* We have never seen this type before, and must figure out its hash and the | 
 |      hashes of the types it cites. | 
 |  | 
 |      Hash this type, and call ourselves recursively.  (The hashing part is | 
 |      optional, and is disabled if overidden_hval is set.)  */ | 
 |  | 
 |   if ((hval = ctf_dedup_rhash_type (fp, input, inputs, parents, input_num, | 
 | 				    type, type_id, tp, name, decorated, | 
 | 				    kind, flags, depth, populate_fun)) == NULL) | 
 |     return NULL;				/* errno is set for us.  */ | 
 |  | 
 |   /* The hash of this type is now known: record it unless caching is unsafe | 
 |      because the hash value will change later.  This will be the final storage | 
 |      of this type's hash, so we call the population function on it.  */ | 
 |  | 
 |   if (!ctf_dedup_is_stub (name, kind, fwdkind, flags)) | 
 |     { | 
 | #ifdef ENABLE_LIBCTF_HASH_DEBUGGING | 
 |       ctf_dprintf ("Caching %lx, ID %p (%s), %s in final location\n", type, | 
 | 		   type_id, name ? name : "", hval); | 
 | #endif | 
 |  | 
 |       if (ctf_dynhash_cinsert (d->cd_type_hashes, type_id, hval) < 0) | 
 | 	{ | 
 | 	  whaterr = N_("error hash caching"); | 
 | 	  goto oom; | 
 | 	} | 
 |  | 
 |       if (populate_fun (fp, input, inputs, input_num, type, type_id, | 
 | 			decorated, hval) < 0) | 
 | 	{ | 
 | 	  whaterr = N_("error calling population function"); | 
 | 	  goto err;				/* errno is set for us. */ | 
 | 	} | 
 |     } | 
 |  | 
 | #ifdef ENABLE_LIBCTF_HASH_DEBUGGING | 
 |   ctf_dprintf ("%lu: Returning final hash for ID %i/%lx: %s\n", depth, | 
 | 	       input_num, type, hval); | 
 | #endif | 
 |   return hval; | 
 |  | 
 |  oom: | 
 |   ctf_set_errno (fp, errno); | 
 |  err: | 
 |   ctf_err_warn (fp, 0, 0, _("%s (%i): %s: during type hashing, " | 
 | 			    "type %lx, kind %i"), | 
 | 		ctf_link_input_name (input), input_num, | 
 | 		gettext (whaterr), type, kind); | 
 |   return NULL; | 
 | } | 
 |  | 
 | /* Populate a number of useful mappings not directly used by the hashing | 
 |    machinery: the output mapping, the cd_name_counts mapping from name -> hash | 
 |    -> count of hashval deduplication state for a given hashed type, and the | 
 |    cd_output_first_tu mapping.  */ | 
 |  | 
 | static int | 
 | ctf_dedup_populate_mappings (ctf_dict_t *fp, ctf_dict_t *input _libctf_unused_, | 
 | 			     ctf_dict_t **inputs _libctf_unused_, | 
 | 			     int input_num _libctf_unused_, | 
 | 			     ctf_id_t type _libctf_unused_, void *id, | 
 | 			     const char *decorated_name, | 
 | 			     const char *hval) | 
 | { | 
 |   ctf_dedup_t *d = &fp->ctf_dedup; | 
 |   ctf_dynset_t *type_ids; | 
 |   ctf_dynhash_t *name_counts; | 
 |   long int count; | 
 |  | 
 | #ifdef ENABLE_LIBCTF_HASH_DEBUGGING | 
 |   ctf_dprintf ("Hash %s, %s, into output mapping for %i/%lx @ %s\n", | 
 | 	       hval, decorated_name ? decorated_name : "(unnamed)", | 
 | 	       input_num, type, ctf_link_input_name (input)); | 
 |  | 
 |   const char *orig_hval; | 
 |  | 
 |   /* Make sure we never map a single GID to multiple hash values.  */ | 
 |  | 
 |   if ((orig_hval = ctf_dynhash_lookup (d->cd_output_mapping_guard, id)) != NULL) | 
 |     { | 
 |       /* We can rely on pointer identity here, since all hashes are | 
 | 	 interned.  */ | 
 |       if (!ctf_assert (fp, orig_hval == hval)) | 
 | 	return -1; | 
 |     } | 
 |   else | 
 |     if (ctf_dynhash_cinsert (d->cd_output_mapping_guard, id, hval) < 0) | 
 |       return ctf_set_errno (fp, errno); | 
 | #endif | 
 |  | 
 |   /* Record the type in the output mapping: if this is the first time this type | 
 |      has been seen, also record it in the cd_output_first_gid.  Because we | 
 |      traverse types in TU order and we do not merge types after the hashing | 
 |      phase, this will be the lowest TU this type ever appears in.  */ | 
 |  | 
 |   if ((type_ids = ctf_dynhash_lookup (d->cd_output_mapping, | 
 | 				      hval)) == NULL) | 
 |     { | 
 |       if (ctf_dynhash_cinsert (d->cd_output_first_gid, hval, id) < 0) | 
 | 	return ctf_set_errno (fp, errno); | 
 |  | 
 |       if ((type_ids = ctf_dynset_create (htab_hash_pointer, | 
 | 					 htab_eq_pointer, | 
 | 					 NULL)) == NULL) | 
 | 	return ctf_set_errno (fp, errno); | 
 |       if (ctf_dynhash_insert (d->cd_output_mapping, (void *) hval, | 
 | 			      type_ids) < 0) | 
 | 	{ | 
 | 	  ctf_dynset_destroy (type_ids); | 
 | 	  return ctf_set_errno (fp, errno); | 
 | 	} | 
 |     } | 
 | #ifdef ENABLE_LIBCTF_HASH_DEBUGGING | 
 |     { | 
 |       /* Verify that all types with this hash are of the same kind, and that the | 
 | 	 first TU a type was seen in never falls.  */ | 
 |  | 
 |       int err; | 
 |       const void *one_id; | 
 |       ctf_next_t *i = NULL; | 
 |       int orig_kind = ctf_type_kind_unsliced (input, type); | 
 |       int orig_first_tu; | 
 |  | 
 |       orig_first_tu = CTF_DEDUP_GID_TO_INPUT | 
 | 	(ctf_dynhash_lookup (d->cd_output_first_gid, hval)); | 
 |       if (!ctf_assert (fp, orig_first_tu <= CTF_DEDUP_GID_TO_INPUT (id))) | 
 | 	return -1; | 
 |  | 
 |       while ((err = ctf_dynset_cnext (type_ids, &i, &one_id)) == 0) | 
 | 	{ | 
 | 	  ctf_dict_t *foo = inputs[CTF_DEDUP_GID_TO_INPUT (one_id)]; | 
 | 	  ctf_id_t bar = CTF_DEDUP_GID_TO_TYPE (one_id); | 
 | 	  if (ctf_type_kind_unsliced (foo, bar) != orig_kind) | 
 | 	    { | 
 | 	      ctf_err_warn (fp, 1, 0, "added wrong kind to output mapping " | 
 | 			    "for hash %s named %s: %p/%lx from %s is " | 
 | 			    "kind %i, but newly-added %p/%lx from %s is " | 
 | 			    "kind %i", hval, | 
 | 			    decorated_name ? decorated_name : "(unnamed)", | 
 | 			    (void *) foo, bar, | 
 | 			    ctf_link_input_name (foo), | 
 | 			    ctf_type_kind_unsliced (foo, bar), | 
 | 			    (void *) input, type, | 
 | 			    ctf_link_input_name (input), orig_kind); | 
 | 	      if (!ctf_assert (fp, ctf_type_kind_unsliced (foo, bar) | 
 | 			       == orig_kind)) | 
 | 		return -1; | 
 | 	    } | 
 | 	} | 
 |       if (err != ECTF_NEXT_END) | 
 | 	return ctf_set_errno (fp, err); | 
 |     } | 
 | #endif | 
 |  | 
 |   /* This function will be repeatedly called for the same types many times: | 
 |      don't waste time reinserting the same keys in that case.  */ | 
 |   if (!ctf_dynset_exists (type_ids, id, NULL) | 
 |       && ctf_dynset_insert (type_ids, id) < 0) | 
 |     return ctf_set_errno (fp, errno); | 
 |  | 
 |   /* The rest only needs to happen for types with names.  */ | 
 |   if (!decorated_name) | 
 |     return 0; | 
 |  | 
 |   /* Count the number of occurrences of the hash value for this GID.  */ | 
 |  | 
 |   hval = ctf_dynhash_lookup (d->cd_type_hashes, id); | 
 |  | 
 |   /* Mapping from name -> hash(hashval, count) not already present?  */ | 
 |   if ((name_counts = ctf_dynhash_lookup (d->cd_name_counts, | 
 | 					 decorated_name)) == NULL) | 
 |     { | 
 |       if ((name_counts = ctf_dynhash_create (ctf_hash_string, | 
 | 					     ctf_hash_eq_string, | 
 | 					     NULL, NULL)) == NULL) | 
 | 	  return ctf_set_errno (fp, errno); | 
 |       if (ctf_dynhash_cinsert (d->cd_name_counts, decorated_name, | 
 | 			       name_counts) < 0) | 
 | 	{ | 
 | 	  ctf_dynhash_destroy (name_counts); | 
 | 	  return ctf_set_errno (fp, errno); | 
 | 	} | 
 |     } | 
 |  | 
 |   /* This will, conveniently, return NULL (i.e. 0) for a new entry.  */ | 
 |   count = (long int) (uintptr_t) ctf_dynhash_lookup (name_counts, hval); | 
 |  | 
 |   if (ctf_dynhash_cinsert (name_counts, hval, | 
 | 			   (const void *) (uintptr_t) (count + 1)) < 0) | 
 |     return ctf_set_errno (fp, errno); | 
 |  | 
 |   return 0; | 
 | } | 
 |  | 
 | /* Mark a single hash as corresponding to a conflicting type.  Mark all types | 
 |    that cite it as conflicting as well, terminating the recursive walk only when | 
 |    types that are already conflicted or types do not cite other types are seen. | 
 |    (Tagged structures and unions do not appear in the cd_citers graph, so the | 
 |    walk also terminates there, since any reference to a conflicting structure is | 
 |    just going to reference an unconflicting forward instead: see | 
 |    ctf_dedup_maybe_synthesize_forward.)  */ | 
 |  | 
 | static int | 
 | ctf_dedup_mark_conflicting_hash (ctf_dict_t *fp, const char *hval) | 
 | { | 
 |   ctf_dedup_t *d = &fp->ctf_dedup; | 
 |   ctf_next_t *i = NULL; | 
 |   int err; | 
 |   const void *k; | 
 |   ctf_dynset_t *citers; | 
 |  | 
 |   /* Mark conflicted if not already so marked.  */ | 
 |   if (ctf_dynset_exists (d->cd_conflicting_types, hval, NULL)) | 
 |     return 0; | 
 |  | 
 |   ctf_dprintf ("Marking %s as conflicted\n", hval); | 
 |  | 
 |   if (ctf_dynset_cinsert (d->cd_conflicting_types, hval) < 0) | 
 |     { | 
 |       ctf_dprintf ("Out of memory marking %s as conflicted\n", hval); | 
 |       ctf_set_errno (fp, errno); | 
 |       return -1; | 
 |     } | 
 |  | 
 |   /* If any types cite this type, mark them conflicted too.  */ | 
 |   if ((citers = ctf_dynhash_lookup (d->cd_citers, hval)) == NULL) | 
 |     return 0; | 
 |  | 
 |   while ((err = ctf_dynset_cnext (citers, &i, &k)) == 0) | 
 |     { | 
 |       const char *hv = (const char *) k; | 
 |  | 
 |       if (ctf_dynset_exists (d->cd_conflicting_types, hv, NULL)) | 
 | 	continue; | 
 |  | 
 |       if (ctf_dedup_mark_conflicting_hash (fp, hv) < 0) | 
 | 	{ | 
 | 	  ctf_next_destroy (i); | 
 | 	  return -1;				/* errno is set for us.  */ | 
 | 	} | 
 |     } | 
 |   if (err != ECTF_NEXT_END) | 
 |     return ctf_set_errno (fp, err); | 
 |  | 
 |   return 0; | 
 | } | 
 |  | 
 | /* Look up a type kind from the output mapping, given a type hash value.  */ | 
 | static int | 
 | ctf_dedup_hash_kind (ctf_dict_t *fp, ctf_dict_t **inputs, const char *hash) | 
 | { | 
 |   ctf_dedup_t *d = &fp->ctf_dedup; | 
 |   void *id; | 
 |   ctf_dynset_t *type_ids; | 
 |  | 
 |   /* Precondition: the output mapping is populated.  */ | 
 |   if (!ctf_assert (fp, ctf_dynhash_elements (d->cd_output_mapping) > 0)) | 
 |     return -1; | 
 |  | 
 |   /* Look up some GID from the output hash for this type.  (They are all | 
 |      identical, so we can pick any).  Don't assert if someone calls this | 
 |      function wrongly, but do assert if the output mapping knows about the hash, | 
 |      but has nothing associated with it.  */ | 
 |  | 
 |   type_ids = ctf_dynhash_lookup (d->cd_output_mapping, hash); | 
 |   if (!type_ids) | 
 |     { | 
 |       ctf_dprintf ("Looked up type kind by nonexistent hash %s.\n", hash); | 
 |       return ctf_set_errno (fp, ECTF_INTERNAL); | 
 |     } | 
 |   id = ctf_dynset_lookup_any (type_ids); | 
 |   if (!ctf_assert (fp, id)) | 
 |     return -1; | 
 |  | 
 |   return ctf_type_kind_unsliced (inputs[CTF_DEDUP_GID_TO_INPUT (id)], | 
 | 				 CTF_DEDUP_GID_TO_TYPE (id)); | 
 | } | 
 |  | 
 | /* Used to keep a count of types: i.e. distinct type hash values.  */ | 
 | typedef struct ctf_dedup_type_counter | 
 | { | 
 |   ctf_dict_t *fp; | 
 |   ctf_dict_t **inputs; | 
 |   int num_non_forwards; | 
 | } ctf_dedup_type_counter_t; | 
 |  | 
 | /* Add to the type counter for one name entry from the cd_name_counts.  */ | 
 | static int | 
 | ctf_dedup_count_types (void *key_, void *value _libctf_unused_, void *arg_) | 
 | { | 
 |   const char *hval = (const char *) key_; | 
 |   int kind; | 
 |   ctf_dedup_type_counter_t *arg = (ctf_dedup_type_counter_t *) arg_; | 
 |  | 
 |   kind = ctf_dedup_hash_kind (arg->fp, arg->inputs, hval); | 
 |  | 
 |   /* We rely on ctf_dedup_hash_kind setting the fp to -ECTF_INTERNAL on error to | 
 |      smuggle errors out of here.  */ | 
 |  | 
 |   if (kind != CTF_K_FORWARD) | 
 |     { | 
 |       arg->num_non_forwards++; | 
 |       ctf_dprintf ("Counting hash %s: kind %i: num_non_forwards is %i\n", | 
 | 		   hval, kind, arg->num_non_forwards); | 
 |     } | 
 |  | 
 |   /* We only need to know if there is more than one non-forward (an ambiguous | 
 |      type): don't waste time iterating any more than needed to figure that | 
 |      out.  */ | 
 |  | 
 |   if (arg->num_non_forwards > 1) | 
 |     return 1; | 
 |  | 
 |   return 0; | 
 | } | 
 |  | 
 | /* Detect name ambiguity and mark ambiguous names as conflicting, other than the | 
 |    most common.  */ | 
 | static int | 
 | ctf_dedup_detect_name_ambiguity (ctf_dict_t *fp, ctf_dict_t **inputs) | 
 | { | 
 |   ctf_dedup_t *d = &fp->ctf_dedup; | 
 |   ctf_next_t *i = NULL; | 
 |   void *k; | 
 |   void *v; | 
 |   int err; | 
 |   const char *whaterr; | 
 |  | 
 |   /* Go through cd_name_counts for all CTF namespaces in turn.  */ | 
 |  | 
 |   while ((err = ctf_dynhash_next (d->cd_name_counts, &i, &k, &v)) == 0) | 
 |     { | 
 |       const char *decorated = (const char *) k; | 
 |       ctf_dynhash_t *name_counts = (ctf_dynhash_t *) v; | 
 |       ctf_next_t *j = NULL; | 
 |  | 
 |       /* If this is a forwardable kind or a forward (which we can tell without | 
 | 	 consulting the type because its decorated name has a space as its | 
 | 	 second character: see ctf_decorate_type_name), we are only interested | 
 | 	 in whether this name has many hashes associated with it: any such name | 
 | 	 is necessarily ambiguous, and types with that name are conflicting. | 
 | 	 Once we know whether this is true, we can skip to the next name: so use | 
 | 	 ctf_dynhash_iter_find for efficiency.  */ | 
 |  | 
 |       if (decorated[0] != '\0' && decorated[1] == ' ') | 
 | 	{ | 
 | 	  ctf_dedup_type_counter_t counters = { fp, inputs, 0 }; | 
 | 	  ctf_dynhash_t *counts = (ctf_dynhash_t *) v; | 
 |  | 
 | 	  ctf_dynhash_iter_find (counts, ctf_dedup_count_types, &counters); | 
 |  | 
 | 	  /* Check for assertion failure and pass it up.  */ | 
 | 	  if (ctf_errno (fp) == ECTF_INTERNAL) | 
 | 	    goto assert_err; | 
 |  | 
 | 	  if (counters.num_non_forwards > 1) | 
 | 	    { | 
 | 	      const void *hval_; | 
 |  | 
 | 	      while ((err = ctf_dynhash_cnext (counts, &j, &hval_, NULL)) == 0) | 
 | 		{ | 
 | 		  const char *hval = (const char *) hval_; | 
 | 		  ctf_dynset_t *type_ids; | 
 | 		  void *id; | 
 | 		  int kind; | 
 |  | 
 | 		  /* Dig through the types in this hash to find the non-forwards | 
 | 		     and mark them ambiguous.  */ | 
 |  | 
 | 		  type_ids = ctf_dynhash_lookup (d->cd_output_mapping, hval); | 
 |  | 
 | 		  /* Nonexistent? Must be a forward with no referent.  */ | 
 | 		  if (!type_ids) | 
 | 		    continue; | 
 |  | 
 | 		  id = ctf_dynset_lookup_any (type_ids); | 
 |  | 
 | 		  kind = ctf_type_kind (inputs[CTF_DEDUP_GID_TO_INPUT (id)], | 
 | 					CTF_DEDUP_GID_TO_TYPE (id)); | 
 |  | 
 | 		  if (kind != CTF_K_FORWARD) | 
 | 		    { | 
 | 		      ctf_dprintf ("Marking %p, with hash %s, conflicting: one " | 
 | 				   "of many non-forward GIDs for %s\n", id, | 
 | 				   hval, (char *) k); | 
 | 		      ctf_dedup_mark_conflicting_hash (fp, hval); | 
 | 		    } | 
 | 		} | 
 | 	      if (err != ECTF_NEXT_END) | 
 | 		{ | 
 | 		  whaterr = N_("error marking conflicting structs/unions"); | 
 | 		  goto iterr; | 
 | 		} | 
 | 	    } | 
 | 	} | 
 |       else | 
 | 	{ | 
 | 	  /* This is an ordinary type.  Find the most common type with this | 
 | 	     name, and mark it unconflicting: all others are conflicting.  (We | 
 | 	     cannot do this sort of popularity contest with forwardable types | 
 | 	     because any forwards to that type would be immediately unified with | 
 | 	     the most-popular type on insertion, and we want conflicting structs | 
 | 	     et al to have all forwards left intact, so the user is notified | 
 | 	     that this type is conflicting.  TODO: improve this in future by | 
 | 	     setting such forwards non-root-visible.) | 
 |  | 
 | 	     If multiple distinct types are "most common", pick the one that | 
 | 	     appears first on the link line, and within that, the one with the | 
 | 	     lowest type ID.  (See sort_output_mapping.)  */ | 
 |  | 
 | 	  const void *key; | 
 | 	  const void *count; | 
 | 	  const char *hval; | 
 | 	  long max_hcount = -1; | 
 | 	  void *max_gid = NULL; | 
 | 	  const char *max_hval = NULL; | 
 |  | 
 | 	  if (ctf_dynhash_elements (name_counts) <= 1) | 
 | 	    continue; | 
 |  | 
 | 	  /* First find the most common.  */ | 
 | 	  while ((err = ctf_dynhash_cnext (name_counts, &j, &key, &count)) == 0) | 
 | 	    { | 
 | 	      hval = (const char *) key; | 
 |  | 
 | 	      if ((long int) (uintptr_t) count > max_hcount) | 
 | 		{ | 
 | 		  max_hcount = (long int) (uintptr_t) count; | 
 | 		  max_hval = hval; | 
 | 		  max_gid = ctf_dynhash_lookup (d->cd_output_first_gid, hval); | 
 | 		} | 
 | 	      else if ((long int) (uintptr_t) count == max_hcount) | 
 | 		{ | 
 | 		  void *gid = ctf_dynhash_lookup (d->cd_output_first_gid, hval); | 
 |  | 
 | 		  if (CTF_DEDUP_GID_TO_INPUT(gid) < CTF_DEDUP_GID_TO_INPUT(max_gid) | 
 | 		      || (CTF_DEDUP_GID_TO_INPUT(gid) == CTF_DEDUP_GID_TO_INPUT(max_gid) | 
 | 			  && CTF_DEDUP_GID_TO_TYPE(gid) < CTF_DEDUP_GID_TO_TYPE(max_gid))) | 
 | 		    { | 
 | 		      max_hval = hval; | 
 | 		      max_gid = ctf_dynhash_lookup (d->cd_output_first_gid, hval); | 
 | 		    } | 
 | 		} | 
 | 	    } | 
 | 	  if (err != ECTF_NEXT_END) | 
 | 	    { | 
 | 	      whaterr = N_("error finding commonest conflicting type"); | 
 | 	      goto iterr; | 
 | 	    } | 
 |  | 
 | 	  /* Mark all the others as conflicting.   */ | 
 | 	  while ((err = ctf_dynhash_cnext (name_counts, &j, &key, NULL)) == 0) | 
 | 	    { | 
 | 	      hval = (const char *) key; | 
 | 	      if (strcmp (max_hval, hval) == 0) | 
 | 		continue; | 
 |  | 
 | 	      ctf_dprintf ("Marking %s, an uncommon hash for %s, conflicting\n", | 
 | 			   hval, (const char *) k); | 
 | 	      if (ctf_dedup_mark_conflicting_hash (fp, hval) < 0) | 
 | 		{ | 
 | 		  whaterr = N_("error marking hashes as conflicting"); | 
 | 		  goto err; | 
 | 		} | 
 | 	    } | 
 | 	  if (err != ECTF_NEXT_END) | 
 | 	    { | 
 | 	      whaterr = N_("marking uncommon conflicting types"); | 
 | 	      goto iterr; | 
 | 	    } | 
 | 	} | 
 |     } | 
 |   if (err != ECTF_NEXT_END) | 
 |     { | 
 |       whaterr = N_("scanning for ambiguous names"); | 
 |       goto iterr; | 
 |     } | 
 |  | 
 |   return 0; | 
 |  | 
 |  err: | 
 |   ctf_next_destroy (i); | 
 |   ctf_err_warn (fp, 0, 0, "%s", gettext (whaterr)); | 
 |   return -1;					/* errno is set for us.  */ | 
 |  | 
 |  iterr: | 
 |   ctf_err_warn (fp, 0, err, _("iteration failed: %s"), gettext (whaterr)); | 
 |   return ctf_set_errno (fp, err); | 
 |  | 
 |  assert_err: | 
 |   ctf_next_destroy (i); | 
 |   return -1; 					/* errno is set for us.  */ | 
 | } | 
 |  | 
 | /* Initialize the deduplication machinery.  */ | 
 |  | 
 | static int | 
 | ctf_dedup_init (ctf_dict_t *fp) | 
 | { | 
 |   ctf_dedup_t *d = &fp->ctf_dedup; | 
 |   size_t i; | 
 |  | 
 |   if (ctf_dedup_atoms_init (fp) < 0) | 
 |       goto oom; | 
 |  | 
 | #if IDS_NEED_ALLOCATION | 
 |   if ((d->cd_id_to_dict_t = ctf_dynhash_create (ctf_hash_type_id_key, | 
 | 						ctf_hash_eq_type_id_key, | 
 | 						free, NULL)) == NULL) | 
 |     goto oom; | 
 | #endif | 
 |  | 
 |   for (i = 0; i < 4; i++) | 
 |     { | 
 |       if ((d->cd_decorated_names[i] = ctf_dynhash_create (ctf_hash_string, | 
 | 							  ctf_hash_eq_string, | 
 | 							  NULL, NULL)) == NULL) | 
 | 	goto oom; | 
 |     } | 
 |  | 
 |   if ((d->cd_name_counts | 
 |        = ctf_dynhash_create (ctf_hash_string, | 
 | 			     ctf_hash_eq_string, NULL, | 
 | 			     (ctf_hash_free_fun) ctf_dynhash_destroy)) == NULL) | 
 |     goto oom; | 
 |  | 
 |   if ((d->cd_type_hashes | 
 |        = ctf_dynhash_create (ctf_hash_integer, | 
 | 			     ctf_hash_eq_integer, | 
 | 			     NULL, NULL)) == NULL) | 
 |     goto oom; | 
 |  | 
 |   if ((d->cd_struct_origin | 
 |        = ctf_dynhash_create (ctf_hash_string, | 
 | 			     ctf_hash_eq_string, | 
 | 			     NULL, NULL)) == NULL) | 
 |     goto oom; | 
 |  | 
 |   if ((d->cd_citers | 
 |        = ctf_dynhash_create (ctf_hash_string, | 
 | 			     ctf_hash_eq_string, NULL, | 
 | 			     (ctf_hash_free_fun) ctf_dynset_destroy)) == NULL) | 
 |     goto oom; | 
 |  | 
 |   if ((d->cd_output_mapping | 
 |        = ctf_dynhash_create (ctf_hash_string, | 
 | 			     ctf_hash_eq_string, NULL, | 
 | 			     (ctf_hash_free_fun) ctf_dynset_destroy)) == NULL) | 
 |     goto oom; | 
 |  | 
 |   if ((d->cd_output_first_gid | 
 |        = ctf_dynhash_create (ctf_hash_string, | 
 | 			     ctf_hash_eq_string, | 
 | 			     NULL, NULL)) == NULL) | 
 |     goto oom; | 
 |  | 
 | #ifdef ENABLE_LIBCTF_HASH_DEBUGGING | 
 |   if ((d->cd_output_mapping_guard | 
 |        = ctf_dynhash_create (ctf_hash_integer, | 
 | 			     ctf_hash_eq_integer, NULL, NULL)) == NULL) | 
 |     goto oom; | 
 | #endif | 
 |  | 
 |   if ((d->cd_input_nums | 
 |        = ctf_dynhash_create (ctf_hash_integer, | 
 | 			     ctf_hash_eq_integer, | 
 | 			     NULL, NULL)) == NULL) | 
 |     goto oom; | 
 |  | 
 |   if ((d->cd_emission_struct_members | 
 |        = ctf_dynhash_create (ctf_hash_integer, | 
 | 			     ctf_hash_eq_integer, | 
 | 			     NULL, NULL)) == NULL) | 
 |     goto oom; | 
 |  | 
 |   if ((d->cd_conflicting_types | 
 |        = ctf_dynset_create (htab_hash_string, | 
 | 			    htab_eq_string, NULL)) == NULL) | 
 |     goto oom; | 
 |  | 
 |   return 0; | 
 |  | 
 |  oom: | 
 |   ctf_err_warn (fp, 0, ENOMEM, _("ctf_dedup_init: cannot initialize: " | 
 | 				 "out of memory")); | 
 |   return ctf_set_errno (fp, ENOMEM); | 
 | } | 
 |  | 
 | /* No ctf_dedup calls are allowed after this call other than starting a new | 
 |    deduplication via ctf_dedup (not even ctf_dedup_type_mapping lookups).  */ | 
 | void | 
 | ctf_dedup_fini (ctf_dict_t *fp, ctf_dict_t **outputs, uint32_t noutputs) | 
 | { | 
 |   ctf_dedup_t *d = &fp->ctf_dedup; | 
 |   size_t i; | 
 |  | 
 |   /* ctf_dedup_atoms is kept across links.  */ | 
 | #if IDS_NEED_ALLOCATION | 
 |   ctf_dynhash_destroy (d->cd_id_to_dict_t); | 
 | #endif | 
 |   for (i = 0; i < 4; i++) | 
 |     ctf_dynhash_destroy (d->cd_decorated_names[i]); | 
 |   ctf_dynhash_destroy (d->cd_name_counts); | 
 |   ctf_dynhash_destroy (d->cd_type_hashes); | 
 |   ctf_dynhash_destroy (d->cd_struct_origin); | 
 |   ctf_dynhash_destroy (d->cd_citers); | 
 |   ctf_dynhash_destroy (d->cd_output_mapping); | 
 |   ctf_dynhash_destroy (d->cd_output_first_gid); | 
 | #ifdef ENABLE_LIBCTF_HASH_DEBUGGING | 
 |   ctf_dynhash_destroy (d->cd_output_mapping_guard); | 
 | #endif | 
 |   ctf_dynhash_destroy (d->cd_input_nums); | 
 |   ctf_dynhash_destroy (d->cd_emission_struct_members); | 
 |   ctf_dynset_destroy (d->cd_conflicting_types); | 
 |  | 
 |   /* Free the per-output state.  */ | 
 |   if (outputs) | 
 |     { | 
 |       for (i = 0; i < noutputs; i++) | 
 | 	{ | 
 | 	  ctf_dedup_t *od = &outputs[i]->ctf_dedup; | 
 | 	  ctf_dynhash_destroy (od->cd_output_emission_hashes); | 
 | 	  ctf_dynhash_destroy (od->cd_output_emission_conflicted_forwards); | 
 | 	  ctf_dict_close (od->cd_output); | 
 | 	} | 
 |     } | 
 |   memset (d, 0, sizeof (ctf_dedup_t)); | 
 | } | 
 |  | 
 | /* Return 1 if this type is cited by multiple input dictionaries.  */ | 
 |  | 
 | static int | 
 | ctf_dedup_multiple_input_dicts (ctf_dict_t *output, ctf_dict_t **inputs, | 
 | 				const char *hval) | 
 | { | 
 |   ctf_dedup_t *d = &output->ctf_dedup; | 
 |   ctf_dynset_t *type_ids; | 
 |   ctf_next_t *i = NULL; | 
 |   void *id; | 
 |   ctf_dict_t *found = NULL, *relative_found = NULL; | 
 |   const char *type_id; | 
 |   ctf_dict_t *input_fp; | 
 |   ctf_id_t input_id; | 
 |   const char *name; | 
 |   const char *decorated; | 
 |   int fwdkind; | 
 |   int multiple = 0; | 
 |   int err; | 
 |  | 
 |   type_ids = ctf_dynhash_lookup (d->cd_output_mapping, hval); | 
 |   if (!ctf_assert (output, type_ids)) | 
 |     return -1; | 
 |  | 
 |   /* Scan across the IDs until we find proof that two disjoint dictionaries | 
 |      are referenced.  Exit as soon as possible.  Optimization opportunity, but | 
 |      possibly not worth it, given that this is only executed in | 
 |      CTF_LINK_SHARE_DUPLICATED mode.  */ | 
 |  | 
 |   while ((err = ctf_dynset_next (type_ids, &i, &id)) == 0) | 
 |     { | 
 |       ctf_dict_t *fp = inputs[CTF_DEDUP_GID_TO_INPUT (id)]; | 
 |  | 
 |       if (fp == found || fp == relative_found) | 
 | 	continue; | 
 |  | 
 |       if (!found) | 
 | 	{ | 
 | 	  found = fp; | 
 | 	  continue; | 
 | 	} | 
 |  | 
 |       if (!relative_found | 
 | 	  && (fp->ctf_parent == found || found->ctf_parent == fp)) | 
 | 	{ | 
 | 	  relative_found = fp; | 
 | 	  continue; | 
 | 	} | 
 |  | 
 |       multiple = 1; | 
 |       ctf_next_destroy (i); | 
 |       break; | 
 |     } | 
 |   if ((err != ECTF_NEXT_END) && (err != 0)) | 
 |     { | 
 |       ctf_err_warn (output, 0, err, _("iteration error " | 
 | 				      "propagating conflictedness")); | 
 |       return ctf_set_errno (output, err); | 
 |     } | 
 |  | 
 |   if (multiple) | 
 |     return multiple; | 
 |  | 
 |   /* This type itself does not appear in multiple input dicts: how about another | 
 |      related type with the same name (e.g. a forward if this is a struct, | 
 |      etc).  */ | 
 |  | 
 |   type_id = ctf_dynset_lookup_any (type_ids); | 
 |   if (!ctf_assert (output, type_id)) | 
 |     return -1; | 
 |  | 
 |   input_fp = inputs[CTF_DEDUP_GID_TO_INPUT (type_id)]; | 
 |   input_id = CTF_DEDUP_GID_TO_TYPE (type_id); | 
 |   fwdkind = ctf_type_kind_forwarded (input_fp, input_id); | 
 |   name = ctf_type_name_raw (input_fp, input_id); | 
 |  | 
 |   if ((fwdkind == CTF_K_STRUCT || fwdkind == CTF_K_UNION) | 
 |       && name[0] != '\0') | 
 |     { | 
 |       const void *origin; | 
 |  | 
 |       if ((decorated = ctf_decorate_type_name (output, name, | 
 | 					       fwdkind)) == NULL) | 
 | 	return -1;				/* errno is set for us.  */ | 
 |  | 
 |       origin = ctf_dynhash_lookup (d->cd_struct_origin, decorated); | 
 |       if ((origin != NULL) && (CTF_DEDUP_GID_TO_INPUT (origin) < 0)) | 
 | 	multiple = 1; | 
 |     } | 
 |  | 
 |   return multiple; | 
 | } | 
 |  | 
 | /* Demote unconflicting types which reference only one input, or which reference | 
 |    two inputs where one input is the parent of the other, into conflicting | 
 |    types.  Only used if the link mode is CTF_LINK_SHARE_DUPLICATED.  */ | 
 |  | 
 | static int | 
 | ctf_dedup_conflictify_unshared (ctf_dict_t *output, ctf_dict_t **inputs) | 
 | { | 
 |   ctf_dedup_t *d = &output->ctf_dedup; | 
 |   ctf_next_t *i = NULL; | 
 |   int err; | 
 |   const void *k; | 
 |   ctf_dynset_t *to_mark = NULL; | 
 |  | 
 |   if ((to_mark = ctf_dynset_create (htab_hash_string, htab_eq_string, | 
 | 				    NULL)) == NULL) | 
 |     goto err_no; | 
 |  | 
 |   while ((err = ctf_dynhash_cnext (d->cd_output_mapping, &i, &k, NULL)) == 0) | 
 |     { | 
 |       const char *hval = (const char *) k; | 
 |       int conflicting; | 
 |  | 
 |       /* Types referenced by only one dict, with no type appearing under that | 
 | 	 name elsewhere, are marked conflicting.  */ | 
 |  | 
 |       conflicting = !ctf_dedup_multiple_input_dicts (output, inputs, hval); | 
 |  | 
 |       if (conflicting < 0) | 
 | 	goto err;				/* errno is set for us.  */ | 
 |  | 
 |       if (conflicting) | 
 | 	if (ctf_dynset_cinsert (to_mark, hval) < 0) | 
 | 	  goto err; | 
 |     } | 
 |   if (err != ECTF_NEXT_END) | 
 |     goto iterr; | 
 |  | 
 |   while ((err = ctf_dynset_cnext (to_mark, &i, &k)) == 0) | 
 |     { | 
 |       const char *hval = (const char *) k; | 
 |  | 
 |       if (ctf_dedup_mark_conflicting_hash (output, hval) < 0) | 
 | 	goto err; | 
 |     } | 
 |   if (err != ECTF_NEXT_END) | 
 |     goto iterr; | 
 |  | 
 |   ctf_dynset_destroy (to_mark); | 
 |  | 
 |   return 0; | 
 |  | 
 |  err_no: | 
 |   ctf_set_errno (output, errno); | 
 |  err: | 
 |   err = ctf_errno (output); | 
 |   ctf_next_destroy (i); | 
 |  iterr: | 
 |   ctf_dynset_destroy (to_mark); | 
 |   ctf_err_warn (output, 0, err, _("conflictifying unshared types")); | 
 |   return ctf_set_errno (output, err); | 
 | } | 
 |  | 
 | /* The core deduplicator.  Populate cd_output_mapping in the output ctf_dedup | 
 |    with a mapping of all types that belong in this dictionary and where they | 
 |    come from, and cd_conflicting_types with an indication of whether each type | 
 |    is conflicted or not.  OUTPUT is the top-level output: INPUTS is the array of | 
 |    input dicts; NINPUTS is the size of that array; PARENTS is an NINPUTS-element | 
 |    array with each element corresponding to a input which is a child dict set to | 
 |    the number in the INPUTS array of that input's parent. | 
 |  | 
 |    If CU_MAPPED is set, this is a first pass for a link with a non-empty CU | 
 |    mapping: only one output will result. | 
 |  | 
 |    Only deduplicates: does not emit the types into the output.  Call | 
 |    ctf_dedup_emit afterwards to do that.  */ | 
 |  | 
 | int | 
 | ctf_dedup (ctf_dict_t *output, ctf_dict_t **inputs, uint32_t ninputs, | 
 | 	   uint32_t *parents, int cu_mapped) | 
 | { | 
 |   ctf_dedup_t *d = &output->ctf_dedup; | 
 |   size_t i; | 
 |   ctf_next_t *it = NULL; | 
 |  | 
 |   if (ctf_dedup_init (output) < 0) | 
 |     return -1; 					/* errno is set for us.  */ | 
 |  | 
 |   for (i = 0; i < ninputs; i++) | 
 |     { | 
 |       ctf_dprintf ("Input %i: %s\n", (int) i, ctf_link_input_name (inputs[i])); | 
 |       if (ctf_dynhash_insert (d->cd_input_nums, inputs[i], | 
 | 			      (void *) (uintptr_t) i) < 0) | 
 | 	{ | 
 | 	  ctf_set_errno (output, errno); | 
 | 	  ctf_err_warn (output, 0, errno, _("ctf_dedup: cannot initialize: %s\n"), | 
 | 			ctf_errmsg (errno)); | 
 | 	  goto err; | 
 | 	} | 
 |     } | 
 |  | 
 |   /* Some flags do not apply when CU-mapping: this is not a duplicated link, | 
 |      because there is only one output and we really don't want to end up marking | 
 |      all nonconflicting but appears-only-once types as conflicting (which in the | 
 |      CU-mapped link means we'd mark them all as non-root-visible!).  */ | 
 |   d->cd_link_flags = output->ctf_link_flags; | 
 |   if (cu_mapped) | 
 |     d->cd_link_flags &= ~(CTF_LINK_SHARE_DUPLICATED); | 
 |  | 
 |   /* Compute hash values for all types, recursively, treating child structures | 
 |      and unions equivalent to forwards, and hashing in the name of the referent | 
 |      of each such type into structures, unions, and non-opaque forwards. | 
 |      Populate a mapping from decorated name (including an indication of | 
 |      struct/union/enum namespace) to count of type hash values in | 
 |      cd_name_counts, a mapping from and a mapping from hash values to input type | 
 |      IDs in cd_output_mapping.  */ | 
 |  | 
 |   ctf_dprintf ("Computing type hashes\n"); | 
 |   for (i = 0; i < ninputs; i++) | 
 |     { | 
 |       ctf_id_t id; | 
 |  | 
 |       while ((id = ctf_type_next (inputs[i], &it, NULL, 1)) != CTF_ERR) | 
 | 	{ | 
 | 	  if (ctf_dedup_hash_type (output, inputs[i], inputs, | 
 | 				   parents, i, id, 0, 0, | 
 | 				   ctf_dedup_populate_mappings) == NULL) | 
 | 	    goto err;				/* errno is set for us.  */ | 
 | 	} | 
 |       if (ctf_errno (inputs[i]) != ECTF_NEXT_END) | 
 | 	{ | 
 | 	  ctf_set_errno (output, ctf_errno (inputs[i])); | 
 | 	  ctf_err_warn (output, 0, 0, _("iteration failure " | 
 | 					"computing type hashes")); | 
 | 	  goto err; | 
 | 	} | 
 |     } | 
 |  | 
 |   /* Go through the cd_name_counts name->hash->count mapping for all CTF | 
 |      namespaces: any name with many hashes associated with it at this stage is | 
 |      necessarily ambiguous.  Mark all the hashes except the most common as | 
 |      conflicting in the output.  */ | 
 |  | 
 |   ctf_dprintf ("Detecting type name ambiguity\n"); | 
 |   if (ctf_dedup_detect_name_ambiguity (output, inputs) < 0) | 
 |       goto err;					/* errno is set for us.  */ | 
 |  | 
 |   /* If the link mode is CTF_LINK_SHARE_DUPLICATED, we change any unconflicting | 
 |      types whose output mapping references only one input dict into a | 
 |      conflicting type, so that they end up in the per-CU dictionaries.  */ | 
 |  | 
 |   if (d->cd_link_flags & CTF_LINK_SHARE_DUPLICATED) | 
 |     { | 
 |       ctf_dprintf ("Conflictifying unshared types\n"); | 
 |       if (ctf_dedup_conflictify_unshared (output, inputs) < 0) | 
 | 	goto err;				/* errno is set for us.  */ | 
 |     } | 
 |   return 0; | 
 |  | 
 |  err: | 
 |   ctf_dedup_fini (output, NULL, 0); | 
 |   return -1; | 
 | } | 
 |  | 
 | static int | 
 | ctf_dedup_rwalk_output_mapping (ctf_dict_t *output, ctf_dict_t **inputs, | 
 | 				uint32_t ninputs, uint32_t *parents, | 
 | 				ctf_dynset_t *already_visited, | 
 | 				const char *hval, | 
 | 				int (*visit_fun) (const char *hval, | 
 | 						  ctf_dict_t *output, | 
 | 						  ctf_dict_t **inputs, | 
 | 						  uint32_t ninputs, | 
 | 						  uint32_t *parents, | 
 | 						  int already_visited, | 
 | 						  ctf_dict_t *input, | 
 | 						  ctf_id_t type, | 
 | 						  void *id, | 
 | 						  int depth, | 
 | 						  void *arg), | 
 | 				void *arg, unsigned long depth); | 
 |  | 
 | /* Like ctf_dedup_rwalk_output_mapping (which see), only takes a single target | 
 |    type and visits it.  */ | 
 | static int | 
 | ctf_dedup_rwalk_one_output_mapping (ctf_dict_t *output, | 
 | 				    ctf_dict_t **inputs, uint32_t ninputs, | 
 | 				    uint32_t *parents, | 
 | 				    ctf_dynset_t *already_visited, | 
 | 				    int visited, void *type_id, | 
 | 				    const char *hval, | 
 | 				    int (*visit_fun) (const char *hval, | 
 | 						      ctf_dict_t *output, | 
 | 						      ctf_dict_t **inputs, | 
 | 						      uint32_t ninputs, | 
 | 						      uint32_t *parents, | 
 | 						      int already_visited, | 
 | 						      ctf_dict_t *input, | 
 | 						      ctf_id_t type, | 
 | 						      void *id, | 
 | 						      int depth, | 
 | 						      void *arg), | 
 | 				    void *arg, unsigned long depth) | 
 | { | 
 |   ctf_dedup_t *d = &output->ctf_dedup; | 
 |   ctf_dict_t *fp; | 
 |   int input_num; | 
 |   ctf_id_t type; | 
 |   int ret; | 
 |   const char *whaterr; | 
 |  | 
 |   input_num = CTF_DEDUP_GID_TO_INPUT (type_id); | 
 |   fp = inputs[input_num]; | 
 |   type = CTF_DEDUP_GID_TO_TYPE (type_id); | 
 |  | 
 |   ctf_dprintf ("%lu: Starting walk over type %s, %i/%lx (%p), from %s, " | 
 | 	       "kind %i\n", depth, hval, input_num, type, (void *) fp, | 
 | 	       ctf_link_input_name (fp), ctf_type_kind_unsliced (fp, type)); | 
 |  | 
 |   /* Get the single call we do if this type has already been visited out of the | 
 |      way.  */ | 
 |   if (visited) | 
 |     return visit_fun (hval, output, inputs, ninputs, parents, visited, fp, | 
 | 		      type, type_id, depth, arg); | 
 |  | 
 |   /* This macro is really ugly, but the alternative is repeating this code many | 
 |      times, which is worse.  */ | 
 |  | 
 | #define CTF_TYPE_WALK(type, errlabel, errmsg)				\ | 
 |   do									\ | 
 |     {									\ | 
 |       void *type_id;							\ | 
 |       const char *hashval;						\ | 
 |       int cited_type_input_num = input_num;				\ | 
 | 									\ | 
 |       if ((fp->ctf_flags & LCTF_CHILD) && (LCTF_TYPE_ISPARENT (fp, type))) \ | 
 | 	cited_type_input_num = parents[input_num];			\ | 
 | 									\ | 
 |       type_id = CTF_DEDUP_GID (output, cited_type_input_num, type);	\ | 
 | 									\ | 
 |       if (type == 0)							\ | 
 | 	{								\ | 
 | 	  ctf_dprintf ("Walking: unimplemented type\n");		\ | 
 | 	  break;							\ | 
 | 	}								\ | 
 | 									\ | 
 |       ctf_dprintf ("Looking up ID %i/%lx in type hashes\n",		\ | 
 | 		   cited_type_input_num, type);				\ | 
 |       hashval = ctf_dynhash_lookup (d->cd_type_hashes, type_id);	\ | 
 |       if (!ctf_assert (output, hashval))				\ | 
 | 	{								\ | 
 | 	  whaterr = N_("error looking up ID in type hashes");		\ | 
 | 	  goto errlabel;						\ | 
 | 	}								\ | 
 |       ctf_dprintf ("ID %i/%lx has hash %s\n", cited_type_input_num, type, \ | 
 | 		   hashval);						\ | 
 | 									\ | 
 |       ret = ctf_dedup_rwalk_output_mapping (output, inputs, ninputs, parents, \ | 
 | 					    already_visited, hashval,	\ | 
 | 					    visit_fun, arg, depth);	\ | 
 |       if (ret < 0)							\ | 
 | 	{								\ | 
 | 	  whaterr = errmsg;						\ | 
 | 	  goto errlabel;						\ | 
 | 	}								\ | 
 |     }									\ | 
 |   while (0) | 
 |  | 
 |   switch (ctf_type_kind_unsliced (fp, type)) | 
 |     { | 
 |     case CTF_K_UNKNOWN: | 
 |     case CTF_K_FORWARD: | 
 |     case CTF_K_INTEGER: | 
 |     case CTF_K_FLOAT: | 
 |     case CTF_K_ENUM: | 
 |       /* No types referenced.  */ | 
 |       break; | 
 |  | 
 |     case CTF_K_TYPEDEF: | 
 |     case CTF_K_VOLATILE: | 
 |     case CTF_K_CONST: | 
 |     case CTF_K_RESTRICT: | 
 |     case CTF_K_POINTER: | 
 |     case CTF_K_SLICE: | 
 |       CTF_TYPE_WALK (ctf_type_reference (fp, type), err, | 
 | 		     N_("error during referenced type walk")); | 
 |       break; | 
 |  | 
 |     case CTF_K_ARRAY: | 
 |       { | 
 | 	ctf_arinfo_t ar; | 
 |  | 
 | 	if (ctf_array_info (fp, type, &ar) < 0) | 
 | 	  { | 
 | 	    whaterr = N_("error during array info lookup"); | 
 | 	    goto err_msg; | 
 | 	  } | 
 |  | 
 | 	CTF_TYPE_WALK (ar.ctr_contents, err, | 
 | 		       N_("error during array contents type walk")); | 
 | 	CTF_TYPE_WALK (ar.ctr_index, err, | 
 | 		       N_("error during array index type walk")); | 
 | 	break; | 
 |       } | 
 |  | 
 |     case CTF_K_FUNCTION: | 
 |       { | 
 | 	ctf_funcinfo_t fi; | 
 | 	ctf_id_t *args; | 
 | 	uint32_t j; | 
 |  | 
 | 	if (ctf_func_type_info (fp, type, &fi) < 0) | 
 | 	  { | 
 | 	    whaterr = N_("error during func type info lookup"); | 
 | 	    goto err_msg; | 
 | 	  } | 
 |  | 
 | 	CTF_TYPE_WALK (fi.ctc_return, err, | 
 | 		       N_("error during func return type walk")); | 
 |  | 
 | 	if ((args = calloc (fi.ctc_argc, sizeof (ctf_id_t))) == NULL) | 
 | 	  { | 
 | 	    whaterr = N_("error doing memory allocation"); | 
 | 	    goto err_msg; | 
 | 	  } | 
 |  | 
 | 	if (ctf_func_type_args (fp, type, fi.ctc_argc, args) < 0) | 
 | 	  { | 
 | 	    whaterr = N_("error doing func arg type lookup"); | 
 | 	    free (args); | 
 | 	    goto err_msg; | 
 | 	  } | 
 |  | 
 | 	for (j = 0; j < fi.ctc_argc; j++) | 
 | 	  CTF_TYPE_WALK (args[j], err_free_args, | 
 | 			 N_("error during Func arg type walk")); | 
 | 	free (args); | 
 | 	break; | 
 |  | 
 |       err_free_args: | 
 | 	free (args); | 
 | 	goto err; | 
 |       } | 
 |     case CTF_K_STRUCT: | 
 |     case CTF_K_UNION: | 
 |       /* We do not recursively traverse the members of structures: they are | 
 | 	 emitted later, in a separate pass.  */ | 
 | 	break; | 
 |     default: | 
 |       whaterr = N_("CTF dict corruption: unknown type kind"); | 
 |       goto err_msg; | 
 |     } | 
 |  | 
 |   return visit_fun (hval, output, inputs, ninputs, parents, visited, fp, type, | 
 | 		    type_id, depth, arg); | 
 |  | 
 |  err_msg: | 
 |   ctf_set_errno (output, ctf_errno (fp)); | 
 |   ctf_err_warn (output, 0, 0, _("%s in input file %s at type ID %lx"), | 
 | 		gettext (whaterr), ctf_link_input_name (fp), type); | 
 |  err: | 
 |   return -1; | 
 | } | 
 | /* Recursively traverse the output mapping, and do something with each type | 
 |    visited, from leaves to root.  VISIT_FUN, called as recursion unwinds, | 
 |    returns a negative error code or zero.  Type hashes may be visited more than | 
 |    once, but are not recursed through repeatedly: ALREADY_VISITED tracks whether | 
 |    types have already been visited.  */ | 
 | static int | 
 | ctf_dedup_rwalk_output_mapping (ctf_dict_t *output, ctf_dict_t **inputs, | 
 | 				uint32_t ninputs, uint32_t *parents, | 
 | 				ctf_dynset_t *already_visited, | 
 | 				const char *hval, | 
 | 				int (*visit_fun) (const char *hval, | 
 | 						  ctf_dict_t *output, | 
 | 						  ctf_dict_t **inputs, | 
 | 						  uint32_t ninputs, | 
 | 						  uint32_t *parents, | 
 | 						  int already_visited, | 
 | 						  ctf_dict_t *input, | 
 | 						  ctf_id_t type, | 
 | 						  void *id, | 
 | 						  int depth, | 
 | 						  void *arg), | 
 | 				void *arg, unsigned long depth) | 
 | { | 
 |   ctf_dedup_t *d = &output->ctf_dedup; | 
 |   ctf_next_t *i = NULL; | 
 |   int err; | 
 |   int visited = 1; | 
 |   ctf_dynset_t *type_ids; | 
 |   void *id; | 
 |  | 
 |   depth++; | 
 |  | 
 |   type_ids = ctf_dynhash_lookup (d->cd_output_mapping, hval); | 
 |   if (!type_ids) | 
 |     { | 
 |       ctf_err_warn (output, 0, ECTF_INTERNAL, | 
 | 		    _("looked up type kind by nonexistent hash %s"), hval); | 
 |       return ctf_set_errno (output, ECTF_INTERNAL); | 
 |     } | 
 |  | 
 |   /* Have we seen this type before?  */ | 
 |  | 
 |   if (!ctf_dynset_exists (already_visited, hval, NULL)) | 
 |     { | 
 |       /* Mark as already-visited immediately, to eliminate the possibility of | 
 | 	 cycles: but remember we have not actually visited it yet for the | 
 | 	 upcoming call to the visit_fun.  (All our callers handle cycles | 
 | 	 properly themselves, so we can just abort them aggressively as soon as | 
 | 	 we find ourselves in one.)  */ | 
 |  | 
 |       visited = 0; | 
 |       if (ctf_dynset_cinsert (already_visited, hval) < 0) | 
 | 	{ | 
 | 	  ctf_err_warn (output, 0, ENOMEM, | 
 | 			_("out of memory tracking already-visited types")); | 
 | 	  return ctf_set_errno (output, ENOMEM); | 
 | 	} | 
 |     } | 
 |  | 
 |   /* If this type is marked conflicted, traverse members and call | 
 |      ctf_dedup_rwalk_output_mapping_once on all the unique ones: otherwise, just | 
 |      pick a random one and use it.  */ | 
 |  | 
 |   if (!ctf_dynset_exists (d->cd_conflicting_types, hval, NULL)) | 
 |     { | 
 |       id = ctf_dynset_lookup_any (type_ids); | 
 |       if (!ctf_assert (output, id)) | 
 | 	return -1; | 
 |  | 
 |       return ctf_dedup_rwalk_one_output_mapping (output, inputs, ninputs, | 
 | 						 parents, already_visited, | 
 | 						 visited, id, hval, visit_fun, | 
 | 						 arg, depth); | 
 |     } | 
 |  | 
 |   while ((err = ctf_dynset_next (type_ids, &i, &id)) == 0) | 
 |     { | 
 |       int ret; | 
 |  | 
 |       ret = ctf_dedup_rwalk_one_output_mapping (output, inputs, ninputs, | 
 | 						parents, already_visited, | 
 | 						visited, id, hval, | 
 | 						visit_fun, arg, depth); | 
 |       if (ret < 0) | 
 | 	{ | 
 | 	  ctf_next_destroy (i); | 
 | 	  return ret;				/* errno is set for us.  */ | 
 | 	} | 
 |     } | 
 |   if (err != ECTF_NEXT_END) | 
 |     { | 
 |       ctf_err_warn (output, 0, err, _("cannot walk conflicted type")); | 
 |       return ctf_set_errno (output, err); | 
 |     } | 
 |  | 
 |   return 0; | 
 | } | 
 |  | 
 | typedef struct ctf_sort_om_cb_arg | 
 | { | 
 |   ctf_dict_t **inputs; | 
 |   uint32_t ninputs; | 
 |   ctf_dedup_t *d; | 
 | } ctf_sort_om_cb_arg_t; | 
 |  | 
 | /* Sort the output mapping into order: types first appearing in earlier inputs | 
 |    first, parents preceding children: if types first appear in the same input, | 
 |    sort those with earlier ctf_id_t's first.  */ | 
 | static int | 
 | sort_output_mapping (const ctf_next_hkv_t *one, const ctf_next_hkv_t *two, | 
 | 		     void *arg_) | 
 | { | 
 |   ctf_sort_om_cb_arg_t *arg = (ctf_sort_om_cb_arg_t *) arg_; | 
 |   ctf_dedup_t *d = arg->d; | 
 |   const char *one_hval = (const char *) one->hkv_key; | 
 |   const char *two_hval = (const char *) two->hkv_key; | 
 |   void *one_gid, *two_gid; | 
 |   uint32_t one_ninput; | 
 |   uint32_t two_ninput; | 
 |   ctf_dict_t *one_fp; | 
 |   ctf_dict_t *two_fp; | 
 |   ctf_id_t one_type; | 
 |   ctf_id_t two_type; | 
 |  | 
 |   one_gid = ctf_dynhash_lookup (d->cd_output_first_gid, one_hval); | 
 |   two_gid = ctf_dynhash_lookup (d->cd_output_first_gid, two_hval); | 
 |  | 
 |   one_ninput = CTF_DEDUP_GID_TO_INPUT (one_gid); | 
 |   two_ninput = CTF_DEDUP_GID_TO_INPUT (two_gid); | 
 |  | 
 |   one_type = CTF_DEDUP_GID_TO_TYPE (one_gid); | 
 |   two_type = CTF_DEDUP_GID_TO_TYPE (two_gid); | 
 |  | 
 |   /* It's kind of hard to smuggle an assertion failure out of here.  */ | 
 |   assert (one_ninput < arg->ninputs && two_ninput < arg->ninputs); | 
 |  | 
 |   one_fp = arg->inputs[one_ninput]; | 
 |   two_fp = arg->inputs[two_ninput]; | 
 |  | 
 |   /* Parents before children.  */ | 
 |  | 
 |   if (!(one_fp->ctf_flags & LCTF_CHILD) | 
 |       && (two_fp->ctf_flags & LCTF_CHILD)) | 
 |     return -1; | 
 |   else if ((one_fp->ctf_flags & LCTF_CHILD) | 
 |       && !(two_fp->ctf_flags & LCTF_CHILD)) | 
 |     return 1; | 
 |  | 
 |   /* ninput order, types appearing in earlier TUs first.  */ | 
 |  | 
 |   if (one_ninput < two_ninput) | 
 |     return -1; | 
 |   else if (two_ninput < one_ninput) | 
 |     return 1; | 
 |  | 
 |   /* Same TU.  Earliest ctf_id_t first.  They cannot be the same.  */ | 
 |  | 
 |   assert (one_type != two_type); | 
 |   if (one_type < two_type) | 
 |     return -1; | 
 |   else | 
 |     return 1; | 
 | } | 
 |  | 
 | /* The public entry point to ctf_dedup_rwalk_output_mapping, above.  */ | 
 | static int | 
 | ctf_dedup_walk_output_mapping (ctf_dict_t *output, ctf_dict_t **inputs, | 
 | 			       uint32_t ninputs, uint32_t *parents, | 
 | 			       int (*visit_fun) (const char *hval, | 
 | 						 ctf_dict_t *output, | 
 | 						 ctf_dict_t **inputs, | 
 | 						 uint32_t ninputs, | 
 | 						 uint32_t *parents, | 
 | 						 int already_visited, | 
 | 						 ctf_dict_t *input, | 
 | 						 ctf_id_t type, | 
 | 						 void *id, | 
 | 						 int depth, | 
 | 						 void *arg), | 
 | 			       void *arg) | 
 | { | 
 |   ctf_dynset_t *already_visited; | 
 |   ctf_next_t *i = NULL; | 
 |   ctf_sort_om_cb_arg_t sort_arg; | 
 |   int err; | 
 |   void *k; | 
 |  | 
 |   if ((already_visited = ctf_dynset_create (htab_hash_string, | 
 | 					    htab_eq_string, | 
 | 					    NULL)) == NULL) | 
 |     return ctf_set_errno (output, ENOMEM); | 
 |  | 
 |   sort_arg.inputs = inputs; | 
 |   sort_arg.ninputs = ninputs; | 
 |   sort_arg.d = &output->ctf_dedup; | 
 |  | 
 |   while ((err = ctf_dynhash_next_sorted (output->ctf_dedup.cd_output_mapping, | 
 | 					 &i, &k, NULL, sort_output_mapping, | 
 | 					 &sort_arg)) == 0) | 
 |     { | 
 |       const char *hval = (const char *) k; | 
 |  | 
 |       err = ctf_dedup_rwalk_output_mapping (output, inputs, ninputs, parents, | 
 | 					    already_visited, hval, visit_fun, | 
 | 					    arg, 0); | 
 |       if (err < 0) | 
 | 	{ | 
 | 	  ctf_next_destroy (i); | 
 | 	  goto err;				/* errno is set for us.  */ | 
 | 	} | 
 |     } | 
 |   if (err != ECTF_NEXT_END) | 
 |     { | 
 |       ctf_err_warn (output, 0, err, _("cannot recurse over output mapping")); | 
 |       ctf_set_errno (output, err); | 
 |       goto err; | 
 |     } | 
 |   ctf_dynset_destroy (already_visited); | 
 |  | 
 |   return 0; | 
 |  err: | 
 |   ctf_dynset_destroy (already_visited); | 
 |   return -1; | 
 | } | 
 |  | 
 | /* Possibly synthesise a synthetic forward in TARGET to subsitute for a | 
 |    conflicted per-TU type ID in INPUT with hash HVAL.  Return its CTF ID, or 0 | 
 |    if none was needed.  */ | 
 | static ctf_id_t | 
 | ctf_dedup_maybe_synthesize_forward (ctf_dict_t *output, ctf_dict_t *target, | 
 | 				    ctf_dict_t *input, ctf_id_t id, | 
 | 				    const char *hval) | 
 | { | 
 |   ctf_dedup_t *od = &output->ctf_dedup; | 
 |   ctf_dedup_t *td = &target->ctf_dedup; | 
 |   int kind; | 
 |   int fwdkind; | 
 |   const char *name = ctf_type_name_raw (input, id); | 
 |   const char *decorated; | 
 |   void *v; | 
 |   ctf_id_t emitted_forward; | 
 |  | 
 |   if (!ctf_dynset_exists (od->cd_conflicting_types, hval, NULL) | 
 |       || target->ctf_flags & LCTF_CHILD | 
 |       || name[0] == '\0' | 
 |       || (((kind = ctf_type_kind_unsliced (input, id)) != CTF_K_STRUCT | 
 | 	   && kind != CTF_K_UNION && kind != CTF_K_FORWARD))) | 
 |     return 0; | 
 |  | 
 |   fwdkind = ctf_type_kind_forwarded (input, id); | 
 |  | 
 |   ctf_dprintf ("Using synthetic forward for conflicted struct/union with " | 
 | 	       "hval %s\n", hval); | 
 |  | 
 |   if (!ctf_assert (output, name)) | 
 |     return CTF_ERR; | 
 |  | 
 |   if ((decorated = ctf_decorate_type_name (output, name, fwdkind)) == NULL) | 
 |     return CTF_ERR; | 
 |  | 
 |   if (!ctf_dynhash_lookup_kv (td->cd_output_emission_conflicted_forwards, | 
 | 			      decorated, NULL, &v)) | 
 |     { | 
 |       if ((emitted_forward = ctf_add_forward (target, CTF_ADD_ROOT, name, | 
 | 					      fwdkind)) == CTF_ERR) | 
 | 	{ | 
 | 	  ctf_set_errno (output, ctf_errno (target)); | 
 | 	  return CTF_ERR; | 
 | 	} | 
 |  | 
 |       if (ctf_dynhash_cinsert (td->cd_output_emission_conflicted_forwards, | 
 | 			       decorated, (void *) (uintptr_t) | 
 | 			       emitted_forward) < 0) | 
 | 	{ | 
 | 	  ctf_set_errno (output, ENOMEM); | 
 | 	  return CTF_ERR; | 
 | 	} | 
 |     } | 
 |   else | 
 |     emitted_forward = (ctf_id_t) (uintptr_t) v; | 
 |  | 
 |   ctf_dprintf ("Cross-TU conflicted struct: passing back forward, %lx\n", | 
 | 	       emitted_forward); | 
 |  | 
 |   return emitted_forward; | 
 | } | 
 |  | 
 | /* Map a GID in some INPUT dict, in the form of an input number and a ctf_id_t, | 
 |    into a GID in a target output dict.  If it returns 0, this is the | 
 |    unimplemented type, and the input type must have been 0.  The OUTPUT dict is | 
 |    assumed to be the parent of the TARGET, if it is not the TARGET itself. | 
 |  | 
 |    Returns CTF_ERR on failure.  Responds to an incoming CTF_ERR as an 'id' by | 
 |    returning CTF_ERR, to simplify callers.  Errors are always propagated to the | 
 |    input, even if they relate to the target, for the same reason.  (Target | 
 |    errors are expected to be very rare.) | 
 |  | 
 |    If the type in question is a citation of a conflicted type in a different TU, | 
 |    emit a forward of the right type in its place (if not already emitted), and | 
 |    record that forward in cd_output_emission_conflicted_forwards.  This avoids | 
 |    the need to replicate the entire type graph below this point in the current | 
 |    TU (an appalling waste of space). | 
 |  | 
 |    TODO: maybe replace forwards in the same TU with their referents?  Might | 
 |    make usability a bit better.  */ | 
 |  | 
 | static ctf_id_t | 
 | ctf_dedup_id_to_target (ctf_dict_t *output, ctf_dict_t *target, | 
 | 			ctf_dict_t **inputs, uint32_t ninputs, | 
 | 			uint32_t *parents, ctf_dict_t *input, int input_num, | 
 | 			ctf_id_t id) | 
 | { | 
 |   ctf_dedup_t *od = &output->ctf_dedup; | 
 |   ctf_dedup_t *td = &target->ctf_dedup; | 
 |   ctf_dict_t *err_fp = input; | 
 |   const char *hval; | 
 |   void *target_id; | 
 |   ctf_id_t emitted_forward; | 
 |  | 
 |   /* The target type of an error is an error.  */ | 
 |   if (id == CTF_ERR) | 
 |     return CTF_ERR; | 
 |  | 
 |   /* The unimplemented type's ID never changes.  */ | 
 |   if (!id) | 
 |     { | 
 |       ctf_dprintf ("%i/%lx: unimplemented type\n", input_num, id); | 
 |       return 0; | 
 |     } | 
 |  | 
 |   ctf_dprintf ("Mapping %i/%lx to target %p (%s)\n", input_num, | 
 | 	       id, (void *) target, ctf_link_input_name (target)); | 
 |  | 
 |   /* If the input type is in the parent type space, and this is a child, reset | 
 |      the input to the parent (which must already have been emitted, since | 
 |      emission of parent dicts happens before children).  */ | 
 |   if ((input->ctf_flags & LCTF_CHILD) && (LCTF_TYPE_ISPARENT (input, id))) | 
 |     { | 
 |       if (!ctf_assert (output, parents[input_num] <= ninputs)) | 
 | 	return -1; | 
 |       input = inputs[parents[input_num]]; | 
 |       input_num = parents[input_num]; | 
 |     } | 
 |  | 
 |   hval = ctf_dynhash_lookup (od->cd_type_hashes, | 
 | 			     CTF_DEDUP_GID (output, input_num, id)); | 
 |  | 
 |   if (!ctf_assert (output, hval && td->cd_output_emission_hashes)) | 
 |     return -1; | 
 |  | 
 |   /* If this type is a conflicted tagged structure, union, or forward, | 
 |      substitute a synthetic forward instead, emitting it if need be.  Only do | 
 |      this if the target is in the parent dict: if it's in the child dict, we can | 
 |      just point straight at the thing itself.  Of course, we might be looking in | 
 |      the child dict right now and not find it and have to look in the parent, so | 
 |      we have to do this check twice.  */ | 
 |  | 
 |   emitted_forward = ctf_dedup_maybe_synthesize_forward (output, target, | 
 | 							input, id, hval); | 
 |   switch (emitted_forward) | 
 |     { | 
 |     case 0: /* No forward needed.  */ | 
 |       break; | 
 |     case -1: | 
 |       ctf_set_errno (err_fp, ctf_errno (output)); | 
 |       ctf_err_warn (err_fp, 0, 0, _("cannot add synthetic forward for type " | 
 | 				    "%i/%lx"), input_num, id); | 
 |       return -1; | 
 |     default: | 
 |       return emitted_forward; | 
 |     } | 
 |  | 
 |   ctf_dprintf ("Looking up %i/%lx, hash %s, in target\n", input_num, id, hval); | 
 |  | 
 |   target_id = ctf_dynhash_lookup (td->cd_output_emission_hashes, hval); | 
 |   if (!target_id) | 
 |     { | 
 |       /* Must be in the parent, so this must be a child, and they must not be | 
 | 	 the same dict.  */ | 
 |       ctf_dprintf ("Checking shared parent for target\n"); | 
 |       if (!ctf_assert (output, (target != output) | 
 | 		       && (target->ctf_flags & LCTF_CHILD))) | 
 | 	return -1; | 
 |  | 
 |       target_id = ctf_dynhash_lookup (od->cd_output_emission_hashes, hval); | 
 |  | 
 |       emitted_forward = ctf_dedup_maybe_synthesize_forward (output, output, | 
 | 							    input, id, hval); | 
 |       switch (emitted_forward) | 
 | 	{ | 
 | 	case 0: /* No forward needed.  */ | 
 | 	  break; | 
 | 	case -1: | 
 | 	  ctf_err_warn (err_fp, 0, ctf_errno (output), | 
 | 			_("cannot add synthetic forward for type %i/%lx"), | 
 | 			input_num, id); | 
 | 	  return ctf_set_errno (err_fp, ctf_errno (output)); | 
 | 	default: | 
 | 	  return emitted_forward; | 
 | 	} | 
 |     } | 
 |   if (!ctf_assert (output, target_id)) | 
 |     return -1; | 
 |   return (ctf_id_t) (uintptr_t) target_id; | 
 | } | 
 |  | 
 | /* Emit a single deduplicated TYPE with the given HVAL, located in a given | 
 |    INPUT, with the given (G)ID, into the shared OUTPUT or a | 
 |    possibly-newly-created per-CU dict.  All the types this type depends upon | 
 |    have already been emitted.  (This type itself may also have been emitted.) | 
 |  | 
 |    If the ARG is 1, this is a CU-mapped deduplication round mapping many | 
 |    ctf_dict_t's into precisely one: conflicting types should be marked | 
 |    non-root-visible.  If the ARG is 0, conflicting types go into per-CU | 
 |    dictionaries stored in the input's ctf_dedup.cd_output: otherwise, everything | 
 |    is emitted directly into the output.  No struct/union members are emitted. | 
 |  | 
 |    Optimization opportunity: trace the ancestry of non-root-visible types and | 
 |    elide all that neither have a root-visible type somewhere towards their root, | 
 |    nor have the type visible via any other route (the function info section, | 
 |    data object section, backtrace section etc).  */ | 
 |  | 
 | static int | 
 | ctf_dedup_emit_type (const char *hval, ctf_dict_t *output, ctf_dict_t **inputs, | 
 | 		     uint32_t ninputs, uint32_t *parents, int already_visited, | 
 | 		     ctf_dict_t *input, ctf_id_t type, void *id, int depth, | 
 | 		     void *arg) | 
 | { | 
 |   ctf_dedup_t *d = &output->ctf_dedup; | 
 |   int kind = ctf_type_kind_unsliced (input, type); | 
 |   const char *name; | 
 |   ctf_dict_t *target = output; | 
 |   ctf_dict_t *real_input; | 
 |   const ctf_type_t *tp; | 
 |   int input_num = CTF_DEDUP_GID_TO_INPUT (id); | 
 |   int output_num = (uint32_t) -1;		/* 'shared' */ | 
 |   int cu_mapped = *(int *)arg; | 
 |   int isroot = 1; | 
 |   int is_conflicting; | 
 |  | 
 |   ctf_next_t *i = NULL; | 
 |   ctf_id_t new_type; | 
 |   ctf_id_t ref; | 
 |   ctf_id_t maybe_dup = 0; | 
 |   ctf_encoding_t ep; | 
 |   const char *errtype; | 
 |   int emission_hashed = 0; | 
 |  | 
 |   /* We don't want to re-emit something we've already emitted.  */ | 
 |  | 
 |   if (already_visited) | 
 |     return 0; | 
 |  | 
 |   ctf_dprintf ("%i: Emitting type with hash %s from %s: determining target\n", | 
 | 	       depth, hval, ctf_link_input_name (input)); | 
 |  | 
 |   /* Conflicting types go into a per-CU output dictionary, unless this is a | 
 |      CU-mapped run.  The import is not refcounted, since it goes into the | 
 |      ctf_link_outputs dict of the output that is its parent.  */ | 
 |   is_conflicting = ctf_dynset_exists (d->cd_conflicting_types, hval, NULL); | 
 |  | 
 |   if (is_conflicting && !cu_mapped) | 
 |     { | 
 |       ctf_dprintf ("%i: Type %s in %i/%lx is conflicted: " | 
 | 		   "inserting into per-CU target.\n", | 
 | 		   depth, hval, input_num, type); | 
 |  | 
 |       if (input->ctf_dedup.cd_output) | 
 | 	target = input->ctf_dedup.cd_output; | 
 |       else | 
 | 	{ | 
 | 	  int err; | 
 |  | 
 | 	  if ((target = ctf_create (&err)) == NULL) | 
 | 	    { | 
 | 	      ctf_err_warn (output, 0, err, | 
 | 			    _("cannot create per-CU CTF archive for CU %s"), | 
 | 			    ctf_link_input_name (input)); | 
 | 	      return ctf_set_errno (output, err); | 
 | 	    } | 
 |  | 
 | 	  ctf_import_unref (target, output); | 
 | 	  if (ctf_cuname (input) != NULL) | 
 | 	    ctf_cuname_set (target, ctf_cuname (input)); | 
 | 	  else | 
 | 	    ctf_cuname_set (target, "unnamed-CU"); | 
 | 	  ctf_parent_name_set (target, _CTF_SECTION); | 
 |  | 
 | 	  input->ctf_dedup.cd_output = target; | 
 | 	  input->ctf_link_in_out = target; | 
 | 	  target->ctf_link_in_out = input; | 
 | 	} | 
 |       output_num = input_num; | 
 |     } | 
 |  | 
 |   real_input = input; | 
 |   if ((tp = ctf_lookup_by_id (&real_input, type)) == NULL) | 
 |     { | 
 |       ctf_err_warn (output, 0, ctf_errno (input), | 
 | 		    _("%s: lookup failure for type %lx"), | 
 | 		    ctf_link_input_name (real_input), type); | 
 |       return ctf_set_errno (output, ctf_errno (input)); | 
 |     } | 
 |  | 
 |   name = ctf_strraw (real_input, tp->ctt_name); | 
 |  | 
 |   /* Hide conflicting types, if we were asked to: also hide if a type with this | 
 |      name already exists and is not a forward.  */ | 
 |   if (cu_mapped && is_conflicting) | 
 |     isroot = 0; | 
 |   else if (name | 
 | 	   && (maybe_dup = ctf_lookup_by_rawname (target, kind, name)) != 0) | 
 |     { | 
 |       if (ctf_type_kind (target, maybe_dup) != CTF_K_FORWARD) | 
 | 	isroot = 0; | 
 |     } | 
 |  | 
 |   ctf_dprintf ("%i: Emitting type with hash %s (%s), into target %i/%p\n", | 
 | 	       depth, hval, name ? name : "", input_num, (void *) target); | 
 |  | 
 |   if (!target->ctf_dedup.cd_output_emission_hashes) | 
 |     if ((target->ctf_dedup.cd_output_emission_hashes | 
 | 	 = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string, | 
 | 			      NULL, NULL)) == NULL) | 
 |       goto oom_hash; | 
 |  | 
 |   if (!target->ctf_dedup.cd_output_emission_conflicted_forwards) | 
 |     if ((target->ctf_dedup.cd_output_emission_conflicted_forwards | 
 | 	 = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string, | 
 | 			      NULL, NULL)) == NULL) | 
 |       goto oom_hash; | 
 |  | 
 |   switch (kind) | 
 |     { | 
 |     case CTF_K_UNKNOWN: | 
 |       /* These are types that CTF cannot encode, marked as such by the | 
 | 	 compiler.  */ | 
 |       errtype = _("unknown type"); | 
 |       if ((new_type = ctf_add_unknown (target, isroot, name)) == CTF_ERR) | 
 | 	goto err_target; | 
 |       break; | 
 |     case CTF_K_FORWARD: | 
 |       /* This will do nothing if the type to which this forwards already exists, | 
 | 	 and will be replaced with such a type if it appears later.  */ | 
 |  | 
 |       errtype = _("forward"); | 
 |       if ((new_type = ctf_add_forward (target, isroot, name, | 
 | 				       ctf_type_kind_forwarded (input, type))) | 
 | 	  == CTF_ERR) | 
 | 	goto err_target; | 
 |       break; | 
 |  | 
 |     case CTF_K_FLOAT: | 
 |     case CTF_K_INTEGER: | 
 |       errtype = _("float/int"); | 
 |       if (ctf_type_encoding (input, type, &ep) < 0) | 
 | 	goto err_input;				/* errno is set for us.  */ | 
 |       if ((new_type = ctf_add_encoded (target, isroot, name, &ep, kind)) | 
 | 	  == CTF_ERR) | 
 | 	goto err_target; | 
 |       break; | 
 |  | 
 |     case CTF_K_ENUM: | 
 |       { | 
 | 	int val; | 
 | 	errtype = _("enum"); | 
 | 	if ((new_type = ctf_add_enum (target, isroot, name)) == CTF_ERR) | 
 | 	  goto err_input;				/* errno is set for us.  */ | 
 |  | 
 | 	while ((name = ctf_enum_next (input, type, &i, &val)) != NULL) | 
 | 	  { | 
 | 	    if (ctf_add_enumerator (target, new_type, name, val) < 0) | 
 | 	      { | 
 | 		ctf_err_warn (target, 0, ctf_errno (target), | 
 | 			      _("%s (%i): cannot add enumeration value %s " | 
 | 				"from input type %lx"), | 
 | 			      ctf_link_input_name (input), input_num, name, | 
 | 			      type); | 
 | 		ctf_next_destroy (i); | 
 | 		return ctf_set_errno (output, ctf_errno (target)); | 
 | 	      } | 
 | 	  } | 
 | 	if (ctf_errno (input) != ECTF_NEXT_END) | 
 | 	  goto err_input; | 
 | 	break; | 
 |       } | 
 |  | 
 |     case CTF_K_TYPEDEF: | 
 |       errtype = _("typedef"); | 
 |  | 
 |       ref = ctf_type_reference (input, type); | 
 |       if ((ref = ctf_dedup_id_to_target (output, target, inputs, ninputs, | 
 | 					 parents, input, input_num, | 
 | 					 ref)) == CTF_ERR) | 
 | 	goto err_input;				/* errno is set for us.  */ | 
 |  | 
 |       if ((new_type = ctf_add_typedef (target, isroot, name, ref)) == CTF_ERR) | 
 | 	goto err_target;			/* errno is set for us.  */ | 
 |       break; | 
 |  | 
 |     case CTF_K_VOLATILE: | 
 |     case CTF_K_CONST: | 
 |     case CTF_K_RESTRICT: | 
 |     case CTF_K_POINTER: | 
 |       errtype = _("pointer or cvr-qual"); | 
 |  | 
 |       ref = ctf_type_reference (input, type); | 
 |       if ((ref = ctf_dedup_id_to_target (output, target, inputs, ninputs, | 
 | 					 parents, input, input_num, | 
 | 					 ref)) == CTF_ERR) | 
 | 	goto err_input;				/* errno is set for us.  */ | 
 |  | 
 |       if ((new_type = ctf_add_reftype (target, isroot, ref, kind)) == CTF_ERR) | 
 | 	goto err_target;			/* errno is set for us.  */ | 
 |       break; | 
 |  | 
 |     case CTF_K_SLICE: | 
 |       errtype = _("slice"); | 
 |  | 
 |       if (ctf_type_encoding (input, type, &ep) < 0) | 
 | 	goto err_input;				/* errno is set for us.  */ | 
 |  | 
 |       ref = ctf_type_reference (input, type); | 
 |       if ((ref = ctf_dedup_id_to_target (output, target, inputs, ninputs, | 
 | 					 parents, input, input_num, | 
 | 					 ref)) == CTF_ERR) | 
 | 	goto err_input; | 
 |  | 
 |       if ((new_type = ctf_add_slice (target, isroot, ref, &ep)) == CTF_ERR) | 
 | 	goto err_target; | 
 |       break; | 
 |  | 
 |     case CTF_K_ARRAY: | 
 |       { | 
 | 	ctf_arinfo_t ar; | 
 |  | 
 | 	errtype = _("array info"); | 
 | 	if (ctf_array_info (input, type, &ar) < 0) | 
 | 	  goto err_input; | 
 |  | 
 | 	ar.ctr_contents = ctf_dedup_id_to_target (output, target, inputs, | 
 | 						  ninputs, parents, input, | 
 | 						  input_num, ar.ctr_contents); | 
 | 	ar.ctr_index = ctf_dedup_id_to_target (output, target, inputs, ninputs, | 
 | 					       parents, input, input_num, | 
 | 					       ar.ctr_index); | 
 |  | 
 | 	if (ar.ctr_contents == CTF_ERR || ar.ctr_index == CTF_ERR) | 
 | 	  goto err_input; | 
 |  | 
 | 	if ((new_type = ctf_add_array (target, isroot, &ar)) == CTF_ERR) | 
 | 	  goto err_target; | 
 |  | 
 | 	break; | 
 |       } | 
 |  | 
 |     case CTF_K_FUNCTION: | 
 |       { | 
 | 	ctf_funcinfo_t fi; | 
 | 	ctf_id_t *args; | 
 | 	uint32_t j; | 
 |  | 
 | 	errtype = _("function"); | 
 | 	if (ctf_func_type_info (input, type, &fi) < 0) | 
 | 	  goto err_input; | 
 |  | 
 | 	fi.ctc_return = ctf_dedup_id_to_target (output, target, inputs, ninputs, | 
 | 						parents, input, input_num, | 
 | 						fi.ctc_return); | 
 | 	if (fi.ctc_return == CTF_ERR) | 
 | 	  goto err_input; | 
 |  | 
 | 	if ((args = calloc (fi.ctc_argc, sizeof (ctf_id_t))) == NULL) | 
 | 	  { | 
 | 	    ctf_set_errno (input, ENOMEM); | 
 | 	    goto err_input; | 
 | 	  } | 
 |  | 
 | 	errtype = _("function args"); | 
 | 	if (ctf_func_type_args (input, type, fi.ctc_argc, args) < 0) | 
 | 	  { | 
 | 	    free (args); | 
 | 	    goto err_input; | 
 | 	  } | 
 |  | 
 | 	for (j = 0; j < fi.ctc_argc; j++) | 
 | 	  { | 
 | 	    args[j] = ctf_dedup_id_to_target (output, target, inputs, ninputs, | 
 | 					      parents, input, input_num, | 
 | 					      args[j]); | 
 | 	    if (args[j] == CTF_ERR) | 
 | 	      goto err_input; | 
 | 	  } | 
 |  | 
 | 	if ((new_type = ctf_add_function (target, isroot, | 
 | 					  &fi, args)) == CTF_ERR) | 
 | 	  { | 
 | 	    free (args); | 
 | 	    goto err_target; | 
 | 	  } | 
 | 	free (args); | 
 | 	break; | 
 |       } | 
 |  | 
 |     case CTF_K_STRUCT: | 
 |     case CTF_K_UNION: | 
 |       { | 
 | 	size_t size = ctf_type_size (input, type); | 
 | 	void *out_id; | 
 | 	/* Insert the structure itself, so other types can refer to it.  */ | 
 |  | 
 | 	errtype = _("structure/union"); | 
 | 	if (kind == CTF_K_STRUCT) | 
 | 	  new_type = ctf_add_struct_sized (target, isroot, name, size); | 
 | 	else | 
 | 	  new_type = ctf_add_union_sized (target, isroot, name, size); | 
 |  | 
 | 	if (new_type == CTF_ERR) | 
 | 	  goto err_target; | 
 |  | 
 | 	out_id = CTF_DEDUP_GID (output, output_num, new_type); | 
 | 	ctf_dprintf ("%i: Noting need to emit members of %p -> %p\n", depth, | 
 | 		     id, out_id); | 
 | 	/* Record the need to emit the members of this structure later.  */ | 
 | 	if (ctf_dynhash_insert (d->cd_emission_struct_members, id, out_id) < 0) | 
 | 	  { | 
 | 	    ctf_set_errno (target, errno); | 
 | 	    goto err_target; | 
 | 	  } | 
 | 	break; | 
 |       } | 
 |     default: | 
 |       ctf_err_warn (output, 0, ECTF_CORRUPT, _("%s: unknown type kind for " | 
 | 					       "input type %lx"), | 
 | 		    ctf_link_input_name (input), type); | 
 |       return ctf_set_errno (output, ECTF_CORRUPT); | 
 |     } | 
 |  | 
 |   if (!emission_hashed | 
 |       && new_type != 0 | 
 |       && ctf_dynhash_cinsert (target->ctf_dedup.cd_output_emission_hashes, | 
 | 			      hval, (void *) (uintptr_t) new_type) < 0) | 
 |     { | 
 |       ctf_err_warn (output, 0, ENOMEM, _("out of memory tracking deduplicated " | 
 | 					 "global type IDs")); | 
 | 	return ctf_set_errno (output, ENOMEM); | 
 |     } | 
 |  | 
 |   if (!emission_hashed && new_type != 0) | 
 |     ctf_dprintf ("%i: Inserted %s, %i/%lx -> %lx into emission hash for " | 
 | 		 "target %p (%s)\n", depth, hval, input_num, type, new_type, | 
 | 		 (void *) target, ctf_link_input_name (target)); | 
 |  | 
 |   return 0; | 
 |  | 
 |  oom_hash: | 
 |   ctf_err_warn (output, 0, ENOMEM, _("out of memory creating emission-tracking " | 
 | 				     "hashes")); | 
 |   return ctf_set_errno (output, ENOMEM); | 
 |  | 
 |  err_input: | 
 |   ctf_err_warn (output, 0, ctf_errno (input), | 
 | 		_("%s (%i): while emitting deduplicated %s, error getting " | 
 | 		  "input type %lx"), ctf_link_input_name (input), | 
 | 		input_num, errtype, type); | 
 |   return ctf_set_errno (output, ctf_errno (input)); | 
 |  err_target: | 
 |   ctf_err_warn (output, 0, ctf_errno (target), | 
 | 		_("%s (%i): while emitting deduplicated %s, error emitting " | 
 | 		  "target type from input type %lx"), | 
 | 		ctf_link_input_name (input), input_num, | 
 | 		errtype, type); | 
 |   return ctf_set_errno (output, ctf_errno (target)); | 
 | } | 
 |  | 
 | /* Traverse the cd_emission_struct_members and emit the members of all | 
 |    structures and unions.  All other types are emitted and complete by this | 
 |    point.  */ | 
 |  | 
 | static int | 
 | ctf_dedup_emit_struct_members (ctf_dict_t *output, ctf_dict_t **inputs, | 
 | 			       uint32_t ninputs, uint32_t *parents) | 
 | { | 
 |   ctf_dedup_t *d = &output->ctf_dedup; | 
 |   ctf_next_t *i = NULL; | 
 |   void *input_id, *target_id; | 
 |   int err; | 
 |   ctf_dict_t *err_fp, *input_fp; | 
 |   int input_num; | 
 |   ctf_id_t err_type; | 
 |  | 
 |   while ((err = ctf_dynhash_next (d->cd_emission_struct_members, &i, | 
 | 				  &input_id, &target_id)) == 0) | 
 |     { | 
 |       ctf_next_t *j = NULL; | 
 |       ctf_dict_t *target; | 
 |       uint32_t target_num; | 
 |       ctf_id_t input_type, target_type; | 
 |       ssize_t offset; | 
 |       ctf_id_t membtype; | 
 |       const char *name; | 
 |  | 
 |       input_num = CTF_DEDUP_GID_TO_INPUT (input_id); | 
 |       input_fp = inputs[input_num]; | 
 |       input_type = CTF_DEDUP_GID_TO_TYPE (input_id); | 
 |  | 
 |       /* The output is either -1 (for the shared, parent output dict) or the | 
 | 	 number of the corresponding input.  */ | 
 |       target_num = CTF_DEDUP_GID_TO_INPUT (target_id); | 
 |       if (target_num == (uint32_t) -1) | 
 | 	target = output; | 
 |       else | 
 | 	{ | 
 | 	  target = inputs[target_num]->ctf_dedup.cd_output; | 
 | 	  if (!ctf_assert (output, target)) | 
 | 	    { | 
 | 	      err_fp = output; | 
 | 	      err_type = input_type; | 
 | 	      goto err_target; | 
 | 	    } | 
 | 	} | 
 |       target_type = CTF_DEDUP_GID_TO_TYPE (target_id); | 
 |  | 
 |       while ((offset = ctf_member_next (input_fp, input_type, &j, &name, | 
 | 					&membtype, 0)) >= 0) | 
 | 	{ | 
 | 	  err_fp = target; | 
 | 	  err_type = target_type; | 
 | 	  if ((membtype = ctf_dedup_id_to_target (output, target, inputs, | 
 | 						  ninputs, parents, input_fp, | 
 | 						  input_num, | 
 | 						  membtype)) == CTF_ERR) | 
 | 	    { | 
 | 	      ctf_next_destroy (j); | 
 | 	      goto err_target; | 
 | 	    } | 
 |  | 
 | 	  if (name == NULL) | 
 | 	    name = ""; | 
 | #ifdef ENABLE_LIBCTF_HASH_DEBUGGING | 
 | 	  ctf_dprintf ("Emitting %s, offset %zi\n", name, offset); | 
 | #endif | 
 | 	  if (ctf_add_member_offset (target, target_type, name, | 
 | 				     membtype, offset) < 0) | 
 | 	    { | 
 | 	      ctf_next_destroy (j); | 
 | 	      goto err_target; | 
 | 	    } | 
 | 	} | 
 |       if (ctf_errno (input_fp) != ECTF_NEXT_END) | 
 | 	{ | 
 | 	  err = ctf_errno (input_fp); | 
 | 	  ctf_next_destroy (i); | 
 | 	  goto iterr; | 
 | 	} | 
 |     } | 
 |   if (err != ECTF_NEXT_END) | 
 |     goto iterr; | 
 |  | 
 |   return 0; | 
 |  err_target: | 
 |   ctf_next_destroy (i); | 
 |   ctf_err_warn (output, 0, ctf_errno (err_fp), | 
 | 		_("%s (%i): error emitting members for structure type %lx"), | 
 | 		ctf_link_input_name (input_fp), input_num, err_type); | 
 |   return ctf_set_errno (output, ctf_errno (err_fp)); | 
 |  iterr: | 
 |   ctf_err_warn (output, 0, err, _("iteration failure emitting " | 
 | 				  "structure members")); | 
 |   return ctf_set_errno (output, err); | 
 | } | 
 |  | 
 | /* Emit deduplicated types into the outputs.  The shared type repository is | 
 |    OUTPUT, on which the ctf_dedup function must have already been called.  The | 
 |    PARENTS array contains the INPUTS index of the parent dict for every child | 
 |    dict at the corresponding index in the INPUTS (for non-child dicts, the value | 
 |    is undefined). | 
 |  | 
 |    Return an array of fps with content emitted into them (starting with OUTPUT, | 
 |    which is the parent of all others, then all the newly-generated outputs). | 
 |  | 
 |    If CU_MAPPED is set, this is a first pass for a link with a non-empty CU | 
 |    mapping: only one output will result.  */ | 
 |  | 
 | ctf_dict_t ** | 
 | ctf_dedup_emit (ctf_dict_t *output, ctf_dict_t **inputs, uint32_t ninputs, | 
 | 		uint32_t *parents, uint32_t *noutputs, int cu_mapped) | 
 | { | 
 |   size_t num_outputs = 1;		/* Always at least one output: us.  */ | 
 |   ctf_dict_t **outputs; | 
 |   ctf_dict_t **walk; | 
 |   size_t i; | 
 |  | 
 |   ctf_dprintf ("Triggering emission.\n"); | 
 |   if (ctf_dedup_walk_output_mapping (output, inputs, ninputs, parents, | 
 | 				     ctf_dedup_emit_type, &cu_mapped) < 0) | 
 |     return NULL;				/* errno is set for us.  */ | 
 |  | 
 |   ctf_dprintf ("Populating struct members.\n"); | 
 |   if (ctf_dedup_emit_struct_members (output, inputs, ninputs, parents) < 0) | 
 |     return NULL;				/* errno is set for us.  */ | 
 |  | 
 |   for (i = 0; i < ninputs; i++) | 
 |     { | 
 |       if (inputs[i]->ctf_dedup.cd_output) | 
 | 	num_outputs++; | 
 |     } | 
 |  | 
 |   if (!ctf_assert (output, !cu_mapped || (cu_mapped && num_outputs == 1))) | 
 |     return NULL; | 
 |  | 
 |   if ((outputs = calloc (num_outputs, sizeof (ctf_dict_t *))) == NULL) | 
 |     { | 
 |       ctf_err_warn (output, 0, ENOMEM, | 
 | 		    _("out of memory allocating link outputs array")); | 
 |       ctf_set_errno (output, ENOMEM); | 
 |       return NULL; | 
 |     } | 
 |   *noutputs = num_outputs; | 
 |  | 
 |   walk = outputs; | 
 |   *walk = output; | 
 |   output->ctf_refcnt++; | 
 |   walk++; | 
 |  | 
 |   for (i = 0; i < ninputs; i++) | 
 |     { | 
 |       if (inputs[i]->ctf_dedup.cd_output) | 
 | 	{ | 
 | 	  *walk = inputs[i]->ctf_dedup.cd_output; | 
 | 	  inputs[i]->ctf_dedup.cd_output = NULL; | 
 | 	  walk++; | 
 | 	} | 
 |     } | 
 |  | 
 |   return outputs; | 
 | } | 
 |  | 
 | /* Determine what type SRC_FP / SRC_TYPE was emitted as in the FP, which | 
 |    must be the shared dict or have it as a parent: return 0 if none.  The SRC_FP | 
 |    must be a past input to ctf_dedup.  */ | 
 |  | 
 | ctf_id_t | 
 | ctf_dedup_type_mapping (ctf_dict_t *fp, ctf_dict_t *src_fp, ctf_id_t src_type) | 
 | { | 
 |   ctf_dict_t *output = NULL; | 
 |   ctf_dedup_t *d; | 
 |   int input_num; | 
 |   void *num_ptr; | 
 |   void *type_ptr; | 
 |   int found; | 
 |   const char *hval; | 
 |  | 
 |   /* It is an error (an internal error in the caller, in ctf-link.c) to call | 
 |      this with an FP that is not a per-CU output or shared output dict, or with | 
 |      a SRC_FP that was not passed to ctf_dedup as an input; it is an internal | 
 |      error in ctf-dedup for the type passed not to have been hashed, though if | 
 |      the src_fp is a child dict and the type is not a child type, it will have | 
 |      been hashed under the GID corresponding to the parent.  */ | 
 |  | 
 |   if (fp->ctf_dedup.cd_type_hashes != NULL) | 
 |     output = fp; | 
 |   else if (fp->ctf_parent && fp->ctf_parent->ctf_dedup.cd_type_hashes != NULL) | 
 |     output = fp->ctf_parent; | 
 |   else | 
 |     { | 
 |       ctf_set_errno (fp, ECTF_INTERNAL); | 
 |       ctf_err_warn (fp, 0, ECTF_INTERNAL, | 
 | 		    _("dict %p passed to ctf_dedup_type_mapping is not a " | 
 | 		      "deduplicated output"), (void *) fp); | 
 |       return CTF_ERR; | 
 |     } | 
 |  | 
 |   if (src_fp->ctf_parent && ctf_type_isparent (src_fp, src_type)) | 
 |     src_fp = src_fp->ctf_parent; | 
 |  | 
 |   d = &output->ctf_dedup; | 
 |  | 
 |   found = ctf_dynhash_lookup_kv (d->cd_input_nums, src_fp, NULL, &num_ptr); | 
 |   if (!ctf_assert (output, found != 0)) | 
 |     return CTF_ERR;				/* errno is set for us.  */ | 
 |   input_num = (uintptr_t) num_ptr; | 
 |  | 
 |   hval = ctf_dynhash_lookup (d->cd_type_hashes, | 
 | 			     CTF_DEDUP_GID (output, input_num, src_type)); | 
 |  | 
 |   if (!ctf_assert (output, hval != NULL)) | 
 |     return CTF_ERR;				/* errno is set for us.  */ | 
 |  | 
 |   /* The emission hashes may be unset if this dict was created after | 
 |      deduplication to house variables or other things that would conflict if | 
 |      stored in the shared dict.  */ | 
 |   if (fp->ctf_dedup.cd_output_emission_hashes) | 
 |     if (ctf_dynhash_lookup_kv (fp->ctf_dedup.cd_output_emission_hashes, hval, | 
 | 			       NULL, &type_ptr)) | 
 |       return (ctf_id_t) (uintptr_t) type_ptr; | 
 |  | 
 |   if (fp->ctf_parent) | 
 |     { | 
 |       ctf_dict_t *pfp = fp->ctf_parent; | 
 |       if (pfp->ctf_dedup.cd_output_emission_hashes) | 
 | 	if (ctf_dynhash_lookup_kv (pfp->ctf_dedup.cd_output_emission_hashes, | 
 | 				   hval, NULL, &type_ptr)) | 
 | 	  return (ctf_id_t) (uintptr_t) type_ptr; | 
 |     } | 
 |  | 
 |   return 0; | 
 | } |