1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * This file contains routines that merge one tdata_t tree, called the child, 31*7c478bd9Sstevel@tonic-gate * into another, called the parent. Note that these names are used mainly for 32*7c478bd9Sstevel@tonic-gate * convenience and to represent the direction of the merge. They are not meant 33*7c478bd9Sstevel@tonic-gate * to imply any relationship between the tdata_t graphs prior to the merge. 34*7c478bd9Sstevel@tonic-gate * 35*7c478bd9Sstevel@tonic-gate * tdata_t structures contain two main elements - a hash of iidesc_t nodes, and 36*7c478bd9Sstevel@tonic-gate * a directed graph of tdesc_t nodes, pointed to by the iidesc_t nodes. Simply 37*7c478bd9Sstevel@tonic-gate * put, we merge the tdesc_t graphs, followed by the iidesc_t nodes, and then we 38*7c478bd9Sstevel@tonic-gate * clean up loose ends. 39*7c478bd9Sstevel@tonic-gate * 40*7c478bd9Sstevel@tonic-gate * The algorithm is as follows: 41*7c478bd9Sstevel@tonic-gate * 42*7c478bd9Sstevel@tonic-gate * 1. Mapping iidesc_t nodes 43*7c478bd9Sstevel@tonic-gate * 44*7c478bd9Sstevel@tonic-gate * For each child iidesc_t node, we first try to map its tdesc_t subgraph 45*7c478bd9Sstevel@tonic-gate * against the tdesc_t graph in the parent. For each node in the child subgraph 46*7c478bd9Sstevel@tonic-gate * that exists in the parent, a mapping between the two (between their type IDs) 47*7c478bd9Sstevel@tonic-gate * is established. For the child nodes that cannot be mapped onto existing 48*7c478bd9Sstevel@tonic-gate * parent nodes, a mapping is established between the child node ID and a 49*7c478bd9Sstevel@tonic-gate * newly-allocated ID that the node will use when it is re-created in the 50*7c478bd9Sstevel@tonic-gate * parent. These unmappable nodes are added to the md_tdtba (tdesc_t To Be 51*7c478bd9Sstevel@tonic-gate * Added) hash, which tracks nodes that need to be created in the parent. 52*7c478bd9Sstevel@tonic-gate * 53*7c478bd9Sstevel@tonic-gate * If all of the nodes in the subgraph for an iidesc_t in the child can be 54*7c478bd9Sstevel@tonic-gate * mapped to existing nodes in the parent, then we can try to map the child 55*7c478bd9Sstevel@tonic-gate * iidesc_t onto an iidesc_t in the parent. If we cannot find an equivalent 56*7c478bd9Sstevel@tonic-gate * iidesc_t, or if we were not able to completely map the tdesc_t subgraph(s), 57*7c478bd9Sstevel@tonic-gate * then we add this iidesc_t to the md_iitba (iidesc_t To Be Added) list. This 58*7c478bd9Sstevel@tonic-gate * list tracks iidesc_t nodes that are to be created in the parent. 59*7c478bd9Sstevel@tonic-gate * 60*7c478bd9Sstevel@tonic-gate * While visiting the tdesc_t nodes, we may discover a forward declaration (a 61*7c478bd9Sstevel@tonic-gate * FORWARD tdesc_t) in the parent that is resolved in the child. That is, there 62*7c478bd9Sstevel@tonic-gate * may be a structure or union definition in the child with the same name as the 63*7c478bd9Sstevel@tonic-gate * forward declaration in the parent. If we find such a node, we record an 64*7c478bd9Sstevel@tonic-gate * association in the md_fdida (Forward => Definition ID Association) list 65*7c478bd9Sstevel@tonic-gate * between the parent ID of the forward declaration and the ID that the 66*7c478bd9Sstevel@tonic-gate * definition will use when re-created in the parent. 67*7c478bd9Sstevel@tonic-gate * 68*7c478bd9Sstevel@tonic-gate * 2. Creating new tdesc_t nodes (the md_tdtba hash) 69*7c478bd9Sstevel@tonic-gate * 70*7c478bd9Sstevel@tonic-gate * We have now attempted to map all tdesc_t nodes from the child into the 71*7c478bd9Sstevel@tonic-gate * parent, and have, in md_tdtba, a hash of all tdesc_t nodes that need to be 72*7c478bd9Sstevel@tonic-gate * created (or, as we so wittily call it, conjured) in the parent. We iterate 73*7c478bd9Sstevel@tonic-gate * through this hash, creating the indicated tdesc_t nodes. For a given tdesc_t 74*7c478bd9Sstevel@tonic-gate * node, conjuring requires two steps - the copying of the common tdesc_t data 75*7c478bd9Sstevel@tonic-gate * (name, type, etc) from the child node, and the creation of links from the 76*7c478bd9Sstevel@tonic-gate * newly-created node to the parent equivalents of other tdesc_t nodes pointed 77*7c478bd9Sstevel@tonic-gate * to by node being conjured. Note that in some cases, the targets of these 78*7c478bd9Sstevel@tonic-gate * links will be on the md_tdtba hash themselves, and may not have been created 79*7c478bd9Sstevel@tonic-gate * yet. As such, we can't establish the links from these new nodes into the 80*7c478bd9Sstevel@tonic-gate * parent graph. We therefore conjure them with links to nodes in the *child* 81*7c478bd9Sstevel@tonic-gate * graph, and add pointers to the links to be created to the md_tdtbr (tdesc_t 82*7c478bd9Sstevel@tonic-gate * To Be Remapped) hash. For example, a POINTER tdesc_t that could not be 83*7c478bd9Sstevel@tonic-gate * resolved would have its &tdesc_t->t_tdesc added to md_tdtbr. 84*7c478bd9Sstevel@tonic-gate * 85*7c478bd9Sstevel@tonic-gate * 3. Creating new iidesc_t nodes (the md_iitba list) 86*7c478bd9Sstevel@tonic-gate * 87*7c478bd9Sstevel@tonic-gate * When we have completed step 2, all tdesc_t nodes have been created (or 88*7c478bd9Sstevel@tonic-gate * already existed) in the parent. Some of them may have incorrect links (the 89*7c478bd9Sstevel@tonic-gate * members of the md_tdtbr list), but they've all been created. As such, we can 90*7c478bd9Sstevel@tonic-gate * create all of the iidesc_t nodes, as we can attach the tdesc_t subgraph 91*7c478bd9Sstevel@tonic-gate * pointers correctly. We create each node, and attach the pointers to the 92*7c478bd9Sstevel@tonic-gate * appropriate parts of the parent tdesc_t graph. 93*7c478bd9Sstevel@tonic-gate * 94*7c478bd9Sstevel@tonic-gate * 4. Resolving newly-created tdesc_t node links (the md_tdtbr list) 95*7c478bd9Sstevel@tonic-gate * 96*7c478bd9Sstevel@tonic-gate * As in step 3, we rely on the fact that all of the tdesc_t nodes have been 97*7c478bd9Sstevel@tonic-gate * created. Each entry in the md_tdtbr list is a pointer to where a link into 98*7c478bd9Sstevel@tonic-gate * the parent will be established. As saved in the md_tdtbr list, these 99*7c478bd9Sstevel@tonic-gate * pointers point into the child tdesc_t subgraph. We can thus get the target 100*7c478bd9Sstevel@tonic-gate * type ID from the child, look at the ID mapping to determine the desired link 101*7c478bd9Sstevel@tonic-gate * target, and redirect the link accordingly. 102*7c478bd9Sstevel@tonic-gate * 103*7c478bd9Sstevel@tonic-gate * 5. Parent => child forward declaration resolution 104*7c478bd9Sstevel@tonic-gate * 105*7c478bd9Sstevel@tonic-gate * If entries were made in the md_fdida list in step 1, we have forward 106*7c478bd9Sstevel@tonic-gate * declarations in the parent that need to be resolved to their definitions 107*7c478bd9Sstevel@tonic-gate * re-created in step 2 from the child. Using the md_fdida list, we can locate 108*7c478bd9Sstevel@tonic-gate * the definition for the forward declaration, and we can redirect all inbound 109*7c478bd9Sstevel@tonic-gate * edges to the forward declaration node to the actual definition. 110*7c478bd9Sstevel@tonic-gate * 111*7c478bd9Sstevel@tonic-gate * A pox on the house of anyone who changes the algorithm without updating 112*7c478bd9Sstevel@tonic-gate * this comment. 113*7c478bd9Sstevel@tonic-gate */ 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate #include <stdio.h> 116*7c478bd9Sstevel@tonic-gate #include <strings.h> 117*7c478bd9Sstevel@tonic-gate #include <assert.h> 118*7c478bd9Sstevel@tonic-gate #include <pthread.h> 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate #include "ctf_headers.h" 121*7c478bd9Sstevel@tonic-gate #include "ctftools.h" 122*7c478bd9Sstevel@tonic-gate #include "list.h" 123*7c478bd9Sstevel@tonic-gate #include "alist.h" 124*7c478bd9Sstevel@tonic-gate #include "memory.h" 125*7c478bd9Sstevel@tonic-gate #include "traverse.h" 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate typedef struct equiv_data equiv_data_t; 128*7c478bd9Sstevel@tonic-gate typedef struct merge_cb_data merge_cb_data_t; 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate /* 131*7c478bd9Sstevel@tonic-gate * There are two traversals in this file, for equivalency and for tdesc_t 132*7c478bd9Sstevel@tonic-gate * re-creation, that do not fit into the tdtraverse() framework. We have our 133*7c478bd9Sstevel@tonic-gate * own traversal mechanism and ops vector here for those two cases. 134*7c478bd9Sstevel@tonic-gate */ 135*7c478bd9Sstevel@tonic-gate typedef struct tdesc_ops { 136*7c478bd9Sstevel@tonic-gate char *name; 137*7c478bd9Sstevel@tonic-gate int (*equiv)(tdesc_t *, tdesc_t *, equiv_data_t *); 138*7c478bd9Sstevel@tonic-gate tdesc_t *(*conjure)(tdesc_t *, int, merge_cb_data_t *); 139*7c478bd9Sstevel@tonic-gate } tdesc_ops_t; 140*7c478bd9Sstevel@tonic-gate extern tdesc_ops_t tdesc_ops[]; 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate /* 143*7c478bd9Sstevel@tonic-gate * The workhorse structure of tdata_t merging. Holds all lists of nodes to be 144*7c478bd9Sstevel@tonic-gate * processed during various phases of the merge algorithm. 145*7c478bd9Sstevel@tonic-gate */ 146*7c478bd9Sstevel@tonic-gate struct merge_cb_data { 147*7c478bd9Sstevel@tonic-gate tdata_t *md_parent; 148*7c478bd9Sstevel@tonic-gate tdata_t *md_tgt; 149*7c478bd9Sstevel@tonic-gate alist_t *md_ta; /* Type Association */ 150*7c478bd9Sstevel@tonic-gate alist_t *md_fdida; /* Forward -> Definition ID Association */ 151*7c478bd9Sstevel@tonic-gate list_t **md_iitba; /* iidesc_t nodes To Be Added to the parent */ 152*7c478bd9Sstevel@tonic-gate hash_t *md_tdtba; /* tdesc_t nodes To Be Added to the parent */ 153*7c478bd9Sstevel@tonic-gate list_t **md_tdtbr; /* tdesc_t nodes To Be Remapped */ 154*7c478bd9Sstevel@tonic-gate int md_flags; 155*7c478bd9Sstevel@tonic-gate }; /* merge_cb_data_t */ 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate /* 158*7c478bd9Sstevel@tonic-gate * When we first create a tdata_t from stabs data, we will have duplicate nodes. 159*7c478bd9Sstevel@tonic-gate * Normal merges, however, assume that the child tdata_t is already self-unique, 160*7c478bd9Sstevel@tonic-gate * and for speed reasons do not attempt to self-uniquify. If this flag is set, 161*7c478bd9Sstevel@tonic-gate * the merge algorithm will self-uniquify by avoiding the insertion of 162*7c478bd9Sstevel@tonic-gate * duplicates in the md_tdtdba list. 163*7c478bd9Sstevel@tonic-gate */ 164*7c478bd9Sstevel@tonic-gate #define MCD_F_SELFUNIQUIFY 0x1 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate /* 167*7c478bd9Sstevel@tonic-gate * When we merge the CTF data for the modules, we don't want it to contain any 168*7c478bd9Sstevel@tonic-gate * data that can be found in the reference module (usually genunix). If this 169*7c478bd9Sstevel@tonic-gate * flag is set, we're doing a merge between the fully merged tdata_t for this 170*7c478bd9Sstevel@tonic-gate * module and the tdata_t for the reference module, with the data unique to this 171*7c478bd9Sstevel@tonic-gate * module ending up in a third tdata_t. It is this third tdata_t that will end 172*7c478bd9Sstevel@tonic-gate * up in the .SUNW_ctf section for the module. 173*7c478bd9Sstevel@tonic-gate */ 174*7c478bd9Sstevel@tonic-gate #define MCD_F_REFMERGE 0x2 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate /* 177*7c478bd9Sstevel@tonic-gate * Mapping of child type IDs to parent type IDs 178*7c478bd9Sstevel@tonic-gate */ 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate static void 181*7c478bd9Sstevel@tonic-gate add_mapping(alist_t *ta, tid_t srcid, tid_t tgtid) 182*7c478bd9Sstevel@tonic-gate { 183*7c478bd9Sstevel@tonic-gate debug(3, "Adding mapping %u => %u\n", srcid, tgtid); 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate assert(!alist_find(ta, (void *)srcid, NULL)); 186*7c478bd9Sstevel@tonic-gate assert(srcid != 0 && tgtid != 0); 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate alist_add(ta, (void *)srcid, (void *)tgtid); 189*7c478bd9Sstevel@tonic-gate } 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate static tid_t 192*7c478bd9Sstevel@tonic-gate get_mapping(alist_t *ta, int srcid) 193*7c478bd9Sstevel@tonic-gate { 194*7c478bd9Sstevel@tonic-gate long ltgtid; 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate if (alist_find(ta, (void *)srcid, (void **)<gtid)) 197*7c478bd9Sstevel@tonic-gate return ((int)ltgtid); 198*7c478bd9Sstevel@tonic-gate else 199*7c478bd9Sstevel@tonic-gate return (0); 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate /* 203*7c478bd9Sstevel@tonic-gate * Determining equivalence of tdesc_t subgraphs 204*7c478bd9Sstevel@tonic-gate */ 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate struct equiv_data { 207*7c478bd9Sstevel@tonic-gate alist_t *ed_ta; 208*7c478bd9Sstevel@tonic-gate tdesc_t *ed_node; 209*7c478bd9Sstevel@tonic-gate tdesc_t *ed_tgt; 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate int ed_clear_mark; 212*7c478bd9Sstevel@tonic-gate int ed_cur_mark; 213*7c478bd9Sstevel@tonic-gate int ed_selfuniquify; 214*7c478bd9Sstevel@tonic-gate }; /* equiv_data_t */ 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate static int equiv_node(tdesc_t *, tdesc_t *, equiv_data_t *); 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate /*ARGSUSED2*/ 219*7c478bd9Sstevel@tonic-gate static int 220*7c478bd9Sstevel@tonic-gate equiv_intrinsic(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed) 221*7c478bd9Sstevel@tonic-gate { 222*7c478bd9Sstevel@tonic-gate intr_t *si = stdp->t_intr; 223*7c478bd9Sstevel@tonic-gate intr_t *ti = ttdp->t_intr; 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate if (si->intr_type != ti->intr_type || 226*7c478bd9Sstevel@tonic-gate si->intr_signed != ti->intr_signed || 227*7c478bd9Sstevel@tonic-gate si->intr_offset != ti->intr_offset || 228*7c478bd9Sstevel@tonic-gate si->intr_nbits != ti->intr_nbits) 229*7c478bd9Sstevel@tonic-gate return (0); 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate if (si->intr_type == INTR_INT && 232*7c478bd9Sstevel@tonic-gate si->intr_iformat != ti->intr_iformat) 233*7c478bd9Sstevel@tonic-gate return (0); 234*7c478bd9Sstevel@tonic-gate else if (si->intr_type == INTR_REAL && 235*7c478bd9Sstevel@tonic-gate si->intr_fformat != ti->intr_fformat) 236*7c478bd9Sstevel@tonic-gate return (0); 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate return (1); 239*7c478bd9Sstevel@tonic-gate } 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate static int 242*7c478bd9Sstevel@tonic-gate equiv_plain(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed) 243*7c478bd9Sstevel@tonic-gate { 244*7c478bd9Sstevel@tonic-gate return (equiv_node(stdp->t_tdesc, ttdp->t_tdesc, ed)); 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate static int 248*7c478bd9Sstevel@tonic-gate equiv_function(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed) 249*7c478bd9Sstevel@tonic-gate { 250*7c478bd9Sstevel@tonic-gate fndef_t *fn1 = stdp->t_fndef, *fn2 = ttdp->t_fndef; 251*7c478bd9Sstevel@tonic-gate int i; 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate if (fn1->fn_nargs != fn2->fn_nargs || 254*7c478bd9Sstevel@tonic-gate fn1->fn_vargs != fn2->fn_vargs) 255*7c478bd9Sstevel@tonic-gate return (0); 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate if (!equiv_node(fn1->fn_ret, fn2->fn_ret, ed)) 258*7c478bd9Sstevel@tonic-gate return (0); 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate for (i = 0; i < fn1->fn_nargs; i++) { 261*7c478bd9Sstevel@tonic-gate if (!equiv_node(fn1->fn_args[i], fn2->fn_args[i], ed)) 262*7c478bd9Sstevel@tonic-gate return (0); 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate return (1); 266*7c478bd9Sstevel@tonic-gate } 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate static int 269*7c478bd9Sstevel@tonic-gate equiv_array(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed) 270*7c478bd9Sstevel@tonic-gate { 271*7c478bd9Sstevel@tonic-gate ardef_t *ar1 = stdp->t_ardef, *ar2 = ttdp->t_ardef; 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate if (!equiv_node(ar1->ad_contents, ar2->ad_contents, ed) || 274*7c478bd9Sstevel@tonic-gate !equiv_node(ar1->ad_idxtype, ar2->ad_idxtype, ed)) 275*7c478bd9Sstevel@tonic-gate return (0); 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate if (ar1->ad_nelems != ar2->ad_nelems) 278*7c478bd9Sstevel@tonic-gate return (0); 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate return (1); 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate static int 284*7c478bd9Sstevel@tonic-gate equiv_su(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed) 285*7c478bd9Sstevel@tonic-gate { 286*7c478bd9Sstevel@tonic-gate mlist_t *ml1 = stdp->t_members, *ml2 = ttdp->t_members; 287*7c478bd9Sstevel@tonic-gate mlist_t *olm1 = NULL; 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate while (ml1 && ml2) { 290*7c478bd9Sstevel@tonic-gate if (ml1->ml_offset != ml2->ml_offset || 291*7c478bd9Sstevel@tonic-gate strcmp(ml1->ml_name, ml2->ml_name) != 0) 292*7c478bd9Sstevel@tonic-gate return (0); 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate /* 295*7c478bd9Sstevel@tonic-gate * Don't do the recursive equivalency checking more than 296*7c478bd9Sstevel@tonic-gate * we have to. 297*7c478bd9Sstevel@tonic-gate */ 298*7c478bd9Sstevel@tonic-gate if (olm1 == NULL || olm1->ml_type->t_id != ml1->ml_type->t_id) { 299*7c478bd9Sstevel@tonic-gate if (ml1->ml_size != ml2->ml_size || 300*7c478bd9Sstevel@tonic-gate !equiv_node(ml1->ml_type, ml2->ml_type, ed)) 301*7c478bd9Sstevel@tonic-gate return (0); 302*7c478bd9Sstevel@tonic-gate } 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate olm1 = ml1; 305*7c478bd9Sstevel@tonic-gate ml1 = ml1->ml_next; 306*7c478bd9Sstevel@tonic-gate ml2 = ml2->ml_next; 307*7c478bd9Sstevel@tonic-gate } 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate if (ml1 || ml2) 310*7c478bd9Sstevel@tonic-gate return (0); 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate return (1); 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate /*ARGSUSED2*/ 316*7c478bd9Sstevel@tonic-gate static int 317*7c478bd9Sstevel@tonic-gate equiv_enum(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed) 318*7c478bd9Sstevel@tonic-gate { 319*7c478bd9Sstevel@tonic-gate elist_t *el1 = stdp->t_emem; 320*7c478bd9Sstevel@tonic-gate elist_t *el2 = ttdp->t_emem; 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate while (el1 && el2) { 323*7c478bd9Sstevel@tonic-gate if (el1->el_number != el2->el_number || 324*7c478bd9Sstevel@tonic-gate strcmp(el1->el_name, el2->el_name) != 0) 325*7c478bd9Sstevel@tonic-gate return (0); 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate el1 = el1->el_next; 328*7c478bd9Sstevel@tonic-gate el2 = el2->el_next; 329*7c478bd9Sstevel@tonic-gate } 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate if (el1 || el2) 332*7c478bd9Sstevel@tonic-gate return (0); 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate return (1); 335*7c478bd9Sstevel@tonic-gate } 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 338*7c478bd9Sstevel@tonic-gate static int 339*7c478bd9Sstevel@tonic-gate equiv_assert(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed) 340*7c478bd9Sstevel@tonic-gate { 341*7c478bd9Sstevel@tonic-gate /* foul, evil, and very bad - this is a "shouldn't happen" */ 342*7c478bd9Sstevel@tonic-gate assert(1 == 0); 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate return (0); 345*7c478bd9Sstevel@tonic-gate } 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate static int 348*7c478bd9Sstevel@tonic-gate fwd_equiv(tdesc_t *ctdp, tdesc_t *mtdp) 349*7c478bd9Sstevel@tonic-gate { 350*7c478bd9Sstevel@tonic-gate tdesc_t *defn = (ctdp->t_type == FORWARD ? mtdp : ctdp); 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate return (defn->t_type == STRUCT || defn->t_type == UNION); 353*7c478bd9Sstevel@tonic-gate } 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate static int 356*7c478bd9Sstevel@tonic-gate equiv_node(tdesc_t *ctdp, tdesc_t *mtdp, equiv_data_t *ed) 357*7c478bd9Sstevel@tonic-gate { 358*7c478bd9Sstevel@tonic-gate int (*equiv)(); 359*7c478bd9Sstevel@tonic-gate int mapping; 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate if (ctdp->t_emark > ed->ed_clear_mark || 362*7c478bd9Sstevel@tonic-gate mtdp->t_emark > ed->ed_clear_mark) 363*7c478bd9Sstevel@tonic-gate return (ctdp->t_emark == mtdp->t_emark); 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate /* 366*7c478bd9Sstevel@tonic-gate * In normal (non-self-uniquify) mode, we don't want to do equivalency 367*7c478bd9Sstevel@tonic-gate * checking on a subgraph that has already been checked. If a mapping 368*7c478bd9Sstevel@tonic-gate * has already been established for a given child node, we can simply 369*7c478bd9Sstevel@tonic-gate * compare the mapping for the child node with the ID of the parent 370*7c478bd9Sstevel@tonic-gate * node. If we are in self-uniquify mode, then we're comparing two 371*7c478bd9Sstevel@tonic-gate * subgraphs within the child graph, and thus need to ignore any 372*7c478bd9Sstevel@tonic-gate * type mappings that have been created, as they are only valid into the 373*7c478bd9Sstevel@tonic-gate * parent. 374*7c478bd9Sstevel@tonic-gate */ 375*7c478bd9Sstevel@tonic-gate if ((mapping = get_mapping(ed->ed_ta, ctdp->t_id)) > 0 && 376*7c478bd9Sstevel@tonic-gate mapping == mtdp->t_id && !ed->ed_selfuniquify) 377*7c478bd9Sstevel@tonic-gate return (1); 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate if (!streq(ctdp->t_name, mtdp->t_name)) 380*7c478bd9Sstevel@tonic-gate return (0); 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate if (ctdp->t_type != mtdp->t_type) { 383*7c478bd9Sstevel@tonic-gate if (ctdp->t_type == FORWARD || mtdp->t_type == FORWARD) 384*7c478bd9Sstevel@tonic-gate return (fwd_equiv(ctdp, mtdp)); 385*7c478bd9Sstevel@tonic-gate else 386*7c478bd9Sstevel@tonic-gate return (0); 387*7c478bd9Sstevel@tonic-gate } 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate ctdp->t_emark = ed->ed_cur_mark; 390*7c478bd9Sstevel@tonic-gate mtdp->t_emark = ed->ed_cur_mark; 391*7c478bd9Sstevel@tonic-gate ed->ed_cur_mark++; 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate if ((equiv = tdesc_ops[ctdp->t_type].equiv) != NULL) 394*7c478bd9Sstevel@tonic-gate return (equiv(ctdp, mtdp, ed)); 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate return (1); 397*7c478bd9Sstevel@tonic-gate } 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate /* 400*7c478bd9Sstevel@tonic-gate * We perform an equivalency check on two subgraphs by traversing through them 401*7c478bd9Sstevel@tonic-gate * in lockstep. If a given node is equivalent in both the parent and the child, 402*7c478bd9Sstevel@tonic-gate * we mark it in both subgraphs, using the t_emark field, with a monotonically 403*7c478bd9Sstevel@tonic-gate * increasing number. If, in the course of the traversal, we reach a node that 404*7c478bd9Sstevel@tonic-gate * we have visited and numbered during this equivalency check, we have a cycle. 405*7c478bd9Sstevel@tonic-gate * If the previously-visited nodes don't have the same emark, then the edges 406*7c478bd9Sstevel@tonic-gate * that brought us to these nodes are not equivalent, and so the check ends. 407*7c478bd9Sstevel@tonic-gate * If the emarks are the same, the edges are equivalent. We then backtrack and 408*7c478bd9Sstevel@tonic-gate * continue the traversal. If we have exhausted all edges in the subgraph, and 409*7c478bd9Sstevel@tonic-gate * have not found any inequivalent nodes, then the subgraphs are equivalent. 410*7c478bd9Sstevel@tonic-gate */ 411*7c478bd9Sstevel@tonic-gate static int 412*7c478bd9Sstevel@tonic-gate equiv_cb(void *bucket, void *arg) 413*7c478bd9Sstevel@tonic-gate { 414*7c478bd9Sstevel@tonic-gate equiv_data_t *ed = arg; 415*7c478bd9Sstevel@tonic-gate tdesc_t *mtdp = bucket; 416*7c478bd9Sstevel@tonic-gate tdesc_t *ctdp = ed->ed_node; 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate ed->ed_clear_mark = ed->ed_cur_mark + 1; 419*7c478bd9Sstevel@tonic-gate ed->ed_cur_mark = ed->ed_clear_mark + 1; 420*7c478bd9Sstevel@tonic-gate 421*7c478bd9Sstevel@tonic-gate if (equiv_node(ctdp, mtdp, ed)) { 422*7c478bd9Sstevel@tonic-gate debug(3, "equiv_node matched %d %d\n", ctdp->t_id, mtdp->t_id); 423*7c478bd9Sstevel@tonic-gate ed->ed_tgt = mtdp; 424*7c478bd9Sstevel@tonic-gate /* matched. stop looking */ 425*7c478bd9Sstevel@tonic-gate return (-1); 426*7c478bd9Sstevel@tonic-gate } 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate return (0); 429*7c478bd9Sstevel@tonic-gate } 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 432*7c478bd9Sstevel@tonic-gate static int 433*7c478bd9Sstevel@tonic-gate map_td_tree_pre(tdesc_t *ctdp, tdesc_t **ctdpp, void *private) 434*7c478bd9Sstevel@tonic-gate { 435*7c478bd9Sstevel@tonic-gate merge_cb_data_t *mcd = private; 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate if (get_mapping(mcd->md_ta, ctdp->t_id) > 0) 438*7c478bd9Sstevel@tonic-gate return (0); 439*7c478bd9Sstevel@tonic-gate 440*7c478bd9Sstevel@tonic-gate return (1); 441*7c478bd9Sstevel@tonic-gate } 442*7c478bd9Sstevel@tonic-gate 443*7c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 444*7c478bd9Sstevel@tonic-gate static int 445*7c478bd9Sstevel@tonic-gate map_td_tree_post(tdesc_t *ctdp, tdesc_t **ctdpp, void *private) 446*7c478bd9Sstevel@tonic-gate { 447*7c478bd9Sstevel@tonic-gate merge_cb_data_t *mcd = private; 448*7c478bd9Sstevel@tonic-gate equiv_data_t ed; 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate ed.ed_ta = mcd->md_ta; 451*7c478bd9Sstevel@tonic-gate ed.ed_clear_mark = mcd->md_parent->td_curemark; 452*7c478bd9Sstevel@tonic-gate ed.ed_cur_mark = mcd->md_parent->td_curemark + 1; 453*7c478bd9Sstevel@tonic-gate ed.ed_node = ctdp; 454*7c478bd9Sstevel@tonic-gate ed.ed_selfuniquify = 0; 455*7c478bd9Sstevel@tonic-gate 456*7c478bd9Sstevel@tonic-gate debug(3, "map_td_tree_post on %d %s\n", ctdp->t_id, 457*7c478bd9Sstevel@tonic-gate ctdp->t_name == NULL ? "(anon)" : ctdp->t_name); 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate if (hash_find_iter(mcd->md_parent->td_layouthash, ctdp, 460*7c478bd9Sstevel@tonic-gate equiv_cb, &ed) < 0) { 461*7c478bd9Sstevel@tonic-gate /* We found an equivalent node */ 462*7c478bd9Sstevel@tonic-gate if (ed.ed_tgt->t_type == FORWARD && ctdp->t_type != FORWARD) { 463*7c478bd9Sstevel@tonic-gate int id = mcd->md_tgt->td_nextid++; 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate debug(3, "Creating new defn type %d\n", id); 466*7c478bd9Sstevel@tonic-gate add_mapping(mcd->md_ta, ctdp->t_id, id); 467*7c478bd9Sstevel@tonic-gate alist_add(mcd->md_fdida, (void *)(ulong_t)ed.ed_tgt, 468*7c478bd9Sstevel@tonic-gate (void *)(ulong_t)id); 469*7c478bd9Sstevel@tonic-gate hash_add(mcd->md_tdtba, ctdp); 470*7c478bd9Sstevel@tonic-gate } else 471*7c478bd9Sstevel@tonic-gate add_mapping(mcd->md_ta, ctdp->t_id, ed.ed_tgt->t_id); 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate } else if (debug_level > 1 && hash_iter(mcd->md_parent->td_idhash, 474*7c478bd9Sstevel@tonic-gate equiv_cb, &ed) < 0) { 475*7c478bd9Sstevel@tonic-gate /* 476*7c478bd9Sstevel@tonic-gate * We didn't find an equivalent node by looking through the 477*7c478bd9Sstevel@tonic-gate * layout hash, but we somehow found it by performing an 478*7c478bd9Sstevel@tonic-gate * exhaustive search through the entire graph. This usually 479*7c478bd9Sstevel@tonic-gate * means that the "name" hash function is broken. 480*7c478bd9Sstevel@tonic-gate */ 481*7c478bd9Sstevel@tonic-gate terminate("Second pass for %d (%s) == %d\n", ctdp->t_id, 482*7c478bd9Sstevel@tonic-gate (ctdp->t_name ? ctdp->t_name : "(anon)"), ed.ed_tgt->t_id); 483*7c478bd9Sstevel@tonic-gate } else { 484*7c478bd9Sstevel@tonic-gate int id = mcd->md_tgt->td_nextid++; 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate debug(3, "Creating new type %d\n", id); 487*7c478bd9Sstevel@tonic-gate add_mapping(mcd->md_ta, ctdp->t_id, id); 488*7c478bd9Sstevel@tonic-gate hash_add(mcd->md_tdtba, ctdp); 489*7c478bd9Sstevel@tonic-gate } 490*7c478bd9Sstevel@tonic-gate 491*7c478bd9Sstevel@tonic-gate mcd->md_parent->td_curemark = ed.ed_cur_mark + 1; 492*7c478bd9Sstevel@tonic-gate 493*7c478bd9Sstevel@tonic-gate return (1); 494*7c478bd9Sstevel@tonic-gate } 495*7c478bd9Sstevel@tonic-gate 496*7c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 497*7c478bd9Sstevel@tonic-gate static int 498*7c478bd9Sstevel@tonic-gate map_td_tree_self_post(tdesc_t *ctdp, tdesc_t **ctdpp, void *private) 499*7c478bd9Sstevel@tonic-gate { 500*7c478bd9Sstevel@tonic-gate merge_cb_data_t *mcd = private; 501*7c478bd9Sstevel@tonic-gate equiv_data_t ed; 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate ed.ed_ta = mcd->md_ta; 504*7c478bd9Sstevel@tonic-gate ed.ed_clear_mark = mcd->md_parent->td_curemark; 505*7c478bd9Sstevel@tonic-gate ed.ed_cur_mark = mcd->md_parent->td_curemark + 1; 506*7c478bd9Sstevel@tonic-gate ed.ed_node = ctdp; 507*7c478bd9Sstevel@tonic-gate ed.ed_selfuniquify = 1; 508*7c478bd9Sstevel@tonic-gate ed.ed_tgt = NULL; 509*7c478bd9Sstevel@tonic-gate 510*7c478bd9Sstevel@tonic-gate if (hash_find_iter(mcd->md_tdtba, ctdp, equiv_cb, &ed) < 0) { 511*7c478bd9Sstevel@tonic-gate debug(3, "Self check found %d in %d\n", ctdp->t_id, 512*7c478bd9Sstevel@tonic-gate ed.ed_tgt->t_id); 513*7c478bd9Sstevel@tonic-gate add_mapping(mcd->md_ta, ctdp->t_id, 514*7c478bd9Sstevel@tonic-gate get_mapping(mcd->md_ta, ed.ed_tgt->t_id)); 515*7c478bd9Sstevel@tonic-gate } else if (debug_level > 1 && hash_iter(mcd->md_tdtba, 516*7c478bd9Sstevel@tonic-gate equiv_cb, &ed) < 0) { 517*7c478bd9Sstevel@tonic-gate /* 518*7c478bd9Sstevel@tonic-gate * We didn't find an equivalent node using the quick way (going 519*7c478bd9Sstevel@tonic-gate * through the hash normally), but we did find it by iterating 520*7c478bd9Sstevel@tonic-gate * through the entire hash. This usually means that the hash 521*7c478bd9Sstevel@tonic-gate * function is broken. 522*7c478bd9Sstevel@tonic-gate */ 523*7c478bd9Sstevel@tonic-gate terminate("Self-unique second pass for %d (%s) == %d\n", 524*7c478bd9Sstevel@tonic-gate ctdp->t_id, (ctdp->t_name ? ctdp->t_name : "(anon)"), 525*7c478bd9Sstevel@tonic-gate ed.ed_tgt->t_id); 526*7c478bd9Sstevel@tonic-gate } else { 527*7c478bd9Sstevel@tonic-gate int id = mcd->md_tgt->td_nextid++; 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate debug(3, "Creating new type %d\n", id); 530*7c478bd9Sstevel@tonic-gate add_mapping(mcd->md_ta, ctdp->t_id, id); 531*7c478bd9Sstevel@tonic-gate hash_add(mcd->md_tdtba, ctdp); 532*7c478bd9Sstevel@tonic-gate } 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate mcd->md_parent->td_curemark = ed.ed_cur_mark + 1; 535*7c478bd9Sstevel@tonic-gate 536*7c478bd9Sstevel@tonic-gate return (1); 537*7c478bd9Sstevel@tonic-gate } 538*7c478bd9Sstevel@tonic-gate 539*7c478bd9Sstevel@tonic-gate static tdtrav_cb_f map_pre[] = { 540*7c478bd9Sstevel@tonic-gate NULL, 541*7c478bd9Sstevel@tonic-gate map_td_tree_pre, /* intrinsic */ 542*7c478bd9Sstevel@tonic-gate map_td_tree_pre, /* pointer */ 543*7c478bd9Sstevel@tonic-gate map_td_tree_pre, /* array */ 544*7c478bd9Sstevel@tonic-gate map_td_tree_pre, /* function */ 545*7c478bd9Sstevel@tonic-gate map_td_tree_pre, /* struct */ 546*7c478bd9Sstevel@tonic-gate map_td_tree_pre, /* union */ 547*7c478bd9Sstevel@tonic-gate map_td_tree_pre, /* enum */ 548*7c478bd9Sstevel@tonic-gate map_td_tree_pre, /* forward */ 549*7c478bd9Sstevel@tonic-gate map_td_tree_pre, /* typedef */ 550*7c478bd9Sstevel@tonic-gate tdtrav_assert, /* typedef_unres */ 551*7c478bd9Sstevel@tonic-gate map_td_tree_pre, /* volatile */ 552*7c478bd9Sstevel@tonic-gate map_td_tree_pre, /* const */ 553*7c478bd9Sstevel@tonic-gate map_td_tree_pre /* restrict */ 554*7c478bd9Sstevel@tonic-gate }; 555*7c478bd9Sstevel@tonic-gate 556*7c478bd9Sstevel@tonic-gate static tdtrav_cb_f map_post[] = { 557*7c478bd9Sstevel@tonic-gate NULL, 558*7c478bd9Sstevel@tonic-gate map_td_tree_post, /* intrinsic */ 559*7c478bd9Sstevel@tonic-gate map_td_tree_post, /* pointer */ 560*7c478bd9Sstevel@tonic-gate map_td_tree_post, /* array */ 561*7c478bd9Sstevel@tonic-gate map_td_tree_post, /* function */ 562*7c478bd9Sstevel@tonic-gate map_td_tree_post, /* struct */ 563*7c478bd9Sstevel@tonic-gate map_td_tree_post, /* union */ 564*7c478bd9Sstevel@tonic-gate map_td_tree_post, /* enum */ 565*7c478bd9Sstevel@tonic-gate map_td_tree_post, /* forward */ 566*7c478bd9Sstevel@tonic-gate map_td_tree_post, /* typedef */ 567*7c478bd9Sstevel@tonic-gate tdtrav_assert, /* typedef_unres */ 568*7c478bd9Sstevel@tonic-gate map_td_tree_post, /* volatile */ 569*7c478bd9Sstevel@tonic-gate map_td_tree_post, /* const */ 570*7c478bd9Sstevel@tonic-gate map_td_tree_post /* restrict */ 571*7c478bd9Sstevel@tonic-gate }; 572*7c478bd9Sstevel@tonic-gate 573*7c478bd9Sstevel@tonic-gate static tdtrav_cb_f map_self_post[] = { 574*7c478bd9Sstevel@tonic-gate NULL, 575*7c478bd9Sstevel@tonic-gate map_td_tree_self_post, /* intrinsic */ 576*7c478bd9Sstevel@tonic-gate map_td_tree_self_post, /* pointer */ 577*7c478bd9Sstevel@tonic-gate map_td_tree_self_post, /* array */ 578*7c478bd9Sstevel@tonic-gate map_td_tree_self_post, /* function */ 579*7c478bd9Sstevel@tonic-gate map_td_tree_self_post, /* struct */ 580*7c478bd9Sstevel@tonic-gate map_td_tree_self_post, /* union */ 581*7c478bd9Sstevel@tonic-gate map_td_tree_self_post, /* enum */ 582*7c478bd9Sstevel@tonic-gate map_td_tree_self_post, /* forward */ 583*7c478bd9Sstevel@tonic-gate map_td_tree_self_post, /* typedef */ 584*7c478bd9Sstevel@tonic-gate tdtrav_assert, /* typedef_unres */ 585*7c478bd9Sstevel@tonic-gate map_td_tree_self_post, /* volatile */ 586*7c478bd9Sstevel@tonic-gate map_td_tree_self_post, /* const */ 587*7c478bd9Sstevel@tonic-gate map_td_tree_self_post /* restrict */ 588*7c478bd9Sstevel@tonic-gate }; 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate /* 591*7c478bd9Sstevel@tonic-gate * Determining equivalence of iidesc_t nodes 592*7c478bd9Sstevel@tonic-gate */ 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate typedef struct iifind_data { 595*7c478bd9Sstevel@tonic-gate iidesc_t *iif_template; 596*7c478bd9Sstevel@tonic-gate alist_t *iif_ta; 597*7c478bd9Sstevel@tonic-gate int iif_newidx; 598*7c478bd9Sstevel@tonic-gate int iif_refmerge; 599*7c478bd9Sstevel@tonic-gate } iifind_data_t; 600*7c478bd9Sstevel@tonic-gate 601*7c478bd9Sstevel@tonic-gate /* 602*7c478bd9Sstevel@tonic-gate * Check to see if this iidesc_t (node) - the current one on the list we're 603*7c478bd9Sstevel@tonic-gate * iterating through - matches the target one (iif->iif_template). Return -1 604*7c478bd9Sstevel@tonic-gate * if it matches, to stop the iteration. 605*7c478bd9Sstevel@tonic-gate */ 606*7c478bd9Sstevel@tonic-gate static int 607*7c478bd9Sstevel@tonic-gate iidesc_match(void *data, void *arg) 608*7c478bd9Sstevel@tonic-gate { 609*7c478bd9Sstevel@tonic-gate iidesc_t *node = data; 610*7c478bd9Sstevel@tonic-gate iifind_data_t *iif = arg; 611*7c478bd9Sstevel@tonic-gate int i; 612*7c478bd9Sstevel@tonic-gate 613*7c478bd9Sstevel@tonic-gate if (node->ii_type != iif->iif_template->ii_type || 614*7c478bd9Sstevel@tonic-gate !streq(node->ii_name, iif->iif_template->ii_name) || 615*7c478bd9Sstevel@tonic-gate node->ii_dtype->t_id != iif->iif_newidx) 616*7c478bd9Sstevel@tonic-gate return (0); 617*7c478bd9Sstevel@tonic-gate 618*7c478bd9Sstevel@tonic-gate if ((node->ii_type == II_SVAR || node->ii_type == II_SFUN) && 619*7c478bd9Sstevel@tonic-gate !streq(node->ii_owner, iif->iif_template->ii_owner)) 620*7c478bd9Sstevel@tonic-gate return (0); 621*7c478bd9Sstevel@tonic-gate 622*7c478bd9Sstevel@tonic-gate if (node->ii_nargs != iif->iif_template->ii_nargs) 623*7c478bd9Sstevel@tonic-gate return (0); 624*7c478bd9Sstevel@tonic-gate 625*7c478bd9Sstevel@tonic-gate for (i = 0; i < node->ii_nargs; i++) { 626*7c478bd9Sstevel@tonic-gate if (get_mapping(iif->iif_ta, 627*7c478bd9Sstevel@tonic-gate iif->iif_template->ii_args[i]->t_id) != 628*7c478bd9Sstevel@tonic-gate node->ii_args[i]->t_id) 629*7c478bd9Sstevel@tonic-gate return (0); 630*7c478bd9Sstevel@tonic-gate } 631*7c478bd9Sstevel@tonic-gate 632*7c478bd9Sstevel@tonic-gate if (iif->iif_refmerge) { 633*7c478bd9Sstevel@tonic-gate switch (iif->iif_template->ii_type) { 634*7c478bd9Sstevel@tonic-gate case II_GFUN: 635*7c478bd9Sstevel@tonic-gate case II_SFUN: 636*7c478bd9Sstevel@tonic-gate case II_GVAR: 637*7c478bd9Sstevel@tonic-gate case II_SVAR: 638*7c478bd9Sstevel@tonic-gate debug(3, "suppressing duping of %d %s from %s\n", 639*7c478bd9Sstevel@tonic-gate iif->iif_template->ii_type, 640*7c478bd9Sstevel@tonic-gate iif->iif_template->ii_name, 641*7c478bd9Sstevel@tonic-gate (iif->iif_template->ii_owner ? 642*7c478bd9Sstevel@tonic-gate iif->iif_template->ii_owner : "NULL")); 643*7c478bd9Sstevel@tonic-gate return (0); 644*7c478bd9Sstevel@tonic-gate case II_NOT: 645*7c478bd9Sstevel@tonic-gate case II_PSYM: 646*7c478bd9Sstevel@tonic-gate case II_SOU: 647*7c478bd9Sstevel@tonic-gate case II_TYPE: 648*7c478bd9Sstevel@tonic-gate break; 649*7c478bd9Sstevel@tonic-gate } 650*7c478bd9Sstevel@tonic-gate } 651*7c478bd9Sstevel@tonic-gate 652*7c478bd9Sstevel@tonic-gate return (-1); 653*7c478bd9Sstevel@tonic-gate } 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate static int 656*7c478bd9Sstevel@tonic-gate merge_type_cb(void *data, void *arg) 657*7c478bd9Sstevel@tonic-gate { 658*7c478bd9Sstevel@tonic-gate iidesc_t *sii = data; 659*7c478bd9Sstevel@tonic-gate merge_cb_data_t *mcd = arg; 660*7c478bd9Sstevel@tonic-gate iifind_data_t iif; 661*7c478bd9Sstevel@tonic-gate tdtrav_cb_f *post; 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate post = (mcd->md_flags & MCD_F_SELFUNIQUIFY ? map_self_post : map_post); 664*7c478bd9Sstevel@tonic-gate 665*7c478bd9Sstevel@tonic-gate /* Map the tdesc nodes */ 666*7c478bd9Sstevel@tonic-gate (void) iitraverse(sii, &mcd->md_parent->td_curvgen, NULL, map_pre, post, 667*7c478bd9Sstevel@tonic-gate mcd); 668*7c478bd9Sstevel@tonic-gate 669*7c478bd9Sstevel@tonic-gate /* Map the iidesc nodes */ 670*7c478bd9Sstevel@tonic-gate iif.iif_template = sii; 671*7c478bd9Sstevel@tonic-gate iif.iif_ta = mcd->md_ta; 672*7c478bd9Sstevel@tonic-gate iif.iif_newidx = get_mapping(mcd->md_ta, sii->ii_dtype->t_id); 673*7c478bd9Sstevel@tonic-gate iif.iif_refmerge = (mcd->md_flags & MCD_F_REFMERGE); 674*7c478bd9Sstevel@tonic-gate 675*7c478bd9Sstevel@tonic-gate if (hash_match(mcd->md_parent->td_iihash, sii, iidesc_match, 676*7c478bd9Sstevel@tonic-gate &iif) == 1) 677*7c478bd9Sstevel@tonic-gate /* successfully mapped */ 678*7c478bd9Sstevel@tonic-gate return (1); 679*7c478bd9Sstevel@tonic-gate 680*7c478bd9Sstevel@tonic-gate debug(3, "tba %s (%d)\n", (sii->ii_name ? sii->ii_name : "(anon)"), 681*7c478bd9Sstevel@tonic-gate sii->ii_type); 682*7c478bd9Sstevel@tonic-gate 683*7c478bd9Sstevel@tonic-gate list_add(mcd->md_iitba, sii); 684*7c478bd9Sstevel@tonic-gate 685*7c478bd9Sstevel@tonic-gate return (0); 686*7c478bd9Sstevel@tonic-gate } 687*7c478bd9Sstevel@tonic-gate 688*7c478bd9Sstevel@tonic-gate static int 689*7c478bd9Sstevel@tonic-gate remap_node(tdesc_t **tgtp, tdesc_t *oldtgt, int selftid, tdesc_t *newself, 690*7c478bd9Sstevel@tonic-gate merge_cb_data_t *mcd) 691*7c478bd9Sstevel@tonic-gate { 692*7c478bd9Sstevel@tonic-gate tdesc_t *tgt = NULL; 693*7c478bd9Sstevel@tonic-gate tdesc_t template; 694*7c478bd9Sstevel@tonic-gate int oldid = oldtgt->t_id; 695*7c478bd9Sstevel@tonic-gate 696*7c478bd9Sstevel@tonic-gate if (oldid == selftid) { 697*7c478bd9Sstevel@tonic-gate *tgtp = newself; 698*7c478bd9Sstevel@tonic-gate return (1); 699*7c478bd9Sstevel@tonic-gate } 700*7c478bd9Sstevel@tonic-gate 701*7c478bd9Sstevel@tonic-gate if ((template.t_id = get_mapping(mcd->md_ta, oldid)) == 0) 702*7c478bd9Sstevel@tonic-gate terminate("failed to get mapping for tid %d\n", oldid); 703*7c478bd9Sstevel@tonic-gate 704*7c478bd9Sstevel@tonic-gate if (!hash_find(mcd->md_parent->td_idhash, (void *)&template, 705*7c478bd9Sstevel@tonic-gate (void *)&tgt) && (!(mcd->md_flags & MCD_F_REFMERGE) || 706*7c478bd9Sstevel@tonic-gate !hash_find(mcd->md_tgt->td_idhash, (void *)&template, 707*7c478bd9Sstevel@tonic-gate (void *)&tgt))) { 708*7c478bd9Sstevel@tonic-gate debug(3, "Remap couldn't find %d (from %d)\n", template.t_id, 709*7c478bd9Sstevel@tonic-gate oldid); 710*7c478bd9Sstevel@tonic-gate *tgtp = oldtgt; 711*7c478bd9Sstevel@tonic-gate list_add(mcd->md_tdtbr, tgtp); 712*7c478bd9Sstevel@tonic-gate return (0); 713*7c478bd9Sstevel@tonic-gate } 714*7c478bd9Sstevel@tonic-gate 715*7c478bd9Sstevel@tonic-gate *tgtp = tgt; 716*7c478bd9Sstevel@tonic-gate return (1); 717*7c478bd9Sstevel@tonic-gate } 718*7c478bd9Sstevel@tonic-gate 719*7c478bd9Sstevel@tonic-gate static tdesc_t * 720*7c478bd9Sstevel@tonic-gate conjure_template(tdesc_t *old, int newselfid) 721*7c478bd9Sstevel@tonic-gate { 722*7c478bd9Sstevel@tonic-gate tdesc_t *new = xcalloc(sizeof (tdesc_t)); 723*7c478bd9Sstevel@tonic-gate 724*7c478bd9Sstevel@tonic-gate new->t_name = old->t_name ? xstrdup(old->t_name) : NULL; 725*7c478bd9Sstevel@tonic-gate new->t_type = old->t_type; 726*7c478bd9Sstevel@tonic-gate new->t_size = old->t_size; 727*7c478bd9Sstevel@tonic-gate new->t_id = newselfid; 728*7c478bd9Sstevel@tonic-gate new->t_flags = old->t_flags; 729*7c478bd9Sstevel@tonic-gate 730*7c478bd9Sstevel@tonic-gate return (new); 731*7c478bd9Sstevel@tonic-gate } 732*7c478bd9Sstevel@tonic-gate 733*7c478bd9Sstevel@tonic-gate /*ARGSUSED2*/ 734*7c478bd9Sstevel@tonic-gate static tdesc_t * 735*7c478bd9Sstevel@tonic-gate conjure_intrinsic(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 736*7c478bd9Sstevel@tonic-gate { 737*7c478bd9Sstevel@tonic-gate tdesc_t *new = conjure_template(old, newselfid); 738*7c478bd9Sstevel@tonic-gate 739*7c478bd9Sstevel@tonic-gate new->t_intr = xmalloc(sizeof (intr_t)); 740*7c478bd9Sstevel@tonic-gate bcopy(old->t_intr, new->t_intr, sizeof (intr_t)); 741*7c478bd9Sstevel@tonic-gate 742*7c478bd9Sstevel@tonic-gate return (new); 743*7c478bd9Sstevel@tonic-gate } 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate static tdesc_t * 746*7c478bd9Sstevel@tonic-gate conjure_plain(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 747*7c478bd9Sstevel@tonic-gate { 748*7c478bd9Sstevel@tonic-gate tdesc_t *new = conjure_template(old, newselfid); 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate (void) remap_node(&new->t_tdesc, old->t_tdesc, old->t_id, new, mcd); 751*7c478bd9Sstevel@tonic-gate 752*7c478bd9Sstevel@tonic-gate return (new); 753*7c478bd9Sstevel@tonic-gate } 754*7c478bd9Sstevel@tonic-gate 755*7c478bd9Sstevel@tonic-gate static tdesc_t * 756*7c478bd9Sstevel@tonic-gate conjure_function(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 757*7c478bd9Sstevel@tonic-gate { 758*7c478bd9Sstevel@tonic-gate tdesc_t *new = conjure_template(old, newselfid); 759*7c478bd9Sstevel@tonic-gate fndef_t *nfn = xmalloc(sizeof (fndef_t)); 760*7c478bd9Sstevel@tonic-gate fndef_t *ofn = old->t_fndef; 761*7c478bd9Sstevel@tonic-gate int i; 762*7c478bd9Sstevel@tonic-gate 763*7c478bd9Sstevel@tonic-gate (void) remap_node(&nfn->fn_ret, ofn->fn_ret, old->t_id, new, mcd); 764*7c478bd9Sstevel@tonic-gate 765*7c478bd9Sstevel@tonic-gate nfn->fn_nargs = ofn->fn_nargs; 766*7c478bd9Sstevel@tonic-gate nfn->fn_vargs = ofn->fn_vargs; 767*7c478bd9Sstevel@tonic-gate 768*7c478bd9Sstevel@tonic-gate if (nfn->fn_nargs > 0) 769*7c478bd9Sstevel@tonic-gate nfn->fn_args = xcalloc(sizeof (tdesc_t *) * ofn->fn_nargs); 770*7c478bd9Sstevel@tonic-gate 771*7c478bd9Sstevel@tonic-gate for (i = 0; i < ofn->fn_nargs; i++) { 772*7c478bd9Sstevel@tonic-gate (void) remap_node(&nfn->fn_args[i], ofn->fn_args[i], old->t_id, 773*7c478bd9Sstevel@tonic-gate new, mcd); 774*7c478bd9Sstevel@tonic-gate } 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate new->t_fndef = nfn; 777*7c478bd9Sstevel@tonic-gate 778*7c478bd9Sstevel@tonic-gate return (new); 779*7c478bd9Sstevel@tonic-gate } 780*7c478bd9Sstevel@tonic-gate 781*7c478bd9Sstevel@tonic-gate static tdesc_t * 782*7c478bd9Sstevel@tonic-gate conjure_array(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 783*7c478bd9Sstevel@tonic-gate { 784*7c478bd9Sstevel@tonic-gate tdesc_t *new = conjure_template(old, newselfid); 785*7c478bd9Sstevel@tonic-gate ardef_t *nar = xmalloc(sizeof (ardef_t)); 786*7c478bd9Sstevel@tonic-gate ardef_t *oar = old->t_ardef; 787*7c478bd9Sstevel@tonic-gate 788*7c478bd9Sstevel@tonic-gate (void) remap_node(&nar->ad_contents, oar->ad_contents, old->t_id, new, 789*7c478bd9Sstevel@tonic-gate mcd); 790*7c478bd9Sstevel@tonic-gate (void) remap_node(&nar->ad_idxtype, oar->ad_idxtype, old->t_id, new, 791*7c478bd9Sstevel@tonic-gate mcd); 792*7c478bd9Sstevel@tonic-gate 793*7c478bd9Sstevel@tonic-gate nar->ad_nelems = oar->ad_nelems; 794*7c478bd9Sstevel@tonic-gate 795*7c478bd9Sstevel@tonic-gate new->t_ardef = nar; 796*7c478bd9Sstevel@tonic-gate 797*7c478bd9Sstevel@tonic-gate return (new); 798*7c478bd9Sstevel@tonic-gate } 799*7c478bd9Sstevel@tonic-gate 800*7c478bd9Sstevel@tonic-gate static tdesc_t * 801*7c478bd9Sstevel@tonic-gate conjure_su(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 802*7c478bd9Sstevel@tonic-gate { 803*7c478bd9Sstevel@tonic-gate tdesc_t *new = conjure_template(old, newselfid); 804*7c478bd9Sstevel@tonic-gate mlist_t *omem, **nmemp; 805*7c478bd9Sstevel@tonic-gate 806*7c478bd9Sstevel@tonic-gate for (omem = old->t_members, nmemp = &new->t_members; 807*7c478bd9Sstevel@tonic-gate omem; omem = omem->ml_next, nmemp = &((*nmemp)->ml_next)) { 808*7c478bd9Sstevel@tonic-gate *nmemp = xmalloc(sizeof (mlist_t)); 809*7c478bd9Sstevel@tonic-gate (*nmemp)->ml_offset = omem->ml_offset; 810*7c478bd9Sstevel@tonic-gate (*nmemp)->ml_size = omem->ml_size; 811*7c478bd9Sstevel@tonic-gate (*nmemp)->ml_name = xstrdup(omem->ml_name); 812*7c478bd9Sstevel@tonic-gate (void) remap_node(&((*nmemp)->ml_type), omem->ml_type, 813*7c478bd9Sstevel@tonic-gate old->t_id, new, mcd); 814*7c478bd9Sstevel@tonic-gate } 815*7c478bd9Sstevel@tonic-gate *nmemp = NULL; 816*7c478bd9Sstevel@tonic-gate 817*7c478bd9Sstevel@tonic-gate return (new); 818*7c478bd9Sstevel@tonic-gate } 819*7c478bd9Sstevel@tonic-gate 820*7c478bd9Sstevel@tonic-gate /*ARGSUSED2*/ 821*7c478bd9Sstevel@tonic-gate static tdesc_t * 822*7c478bd9Sstevel@tonic-gate conjure_enum(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 823*7c478bd9Sstevel@tonic-gate { 824*7c478bd9Sstevel@tonic-gate tdesc_t *new = conjure_template(old, newselfid); 825*7c478bd9Sstevel@tonic-gate elist_t *oel, **nelp; 826*7c478bd9Sstevel@tonic-gate 827*7c478bd9Sstevel@tonic-gate for (oel = old->t_emem, nelp = &new->t_emem; 828*7c478bd9Sstevel@tonic-gate oel; oel = oel->el_next, nelp = &((*nelp)->el_next)) { 829*7c478bd9Sstevel@tonic-gate *nelp = xmalloc(sizeof (elist_t)); 830*7c478bd9Sstevel@tonic-gate (*nelp)->el_name = xstrdup(oel->el_name); 831*7c478bd9Sstevel@tonic-gate (*nelp)->el_number = oel->el_number; 832*7c478bd9Sstevel@tonic-gate } 833*7c478bd9Sstevel@tonic-gate *nelp = NULL; 834*7c478bd9Sstevel@tonic-gate 835*7c478bd9Sstevel@tonic-gate return (new); 836*7c478bd9Sstevel@tonic-gate } 837*7c478bd9Sstevel@tonic-gate 838*7c478bd9Sstevel@tonic-gate /*ARGSUSED2*/ 839*7c478bd9Sstevel@tonic-gate static tdesc_t * 840*7c478bd9Sstevel@tonic-gate conjure_forward(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 841*7c478bd9Sstevel@tonic-gate { 842*7c478bd9Sstevel@tonic-gate tdesc_t *new = conjure_template(old, newselfid); 843*7c478bd9Sstevel@tonic-gate 844*7c478bd9Sstevel@tonic-gate list_add(&mcd->md_tgt->td_fwdlist, new); 845*7c478bd9Sstevel@tonic-gate 846*7c478bd9Sstevel@tonic-gate return (new); 847*7c478bd9Sstevel@tonic-gate } 848*7c478bd9Sstevel@tonic-gate 849*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 850*7c478bd9Sstevel@tonic-gate static tdesc_t * 851*7c478bd9Sstevel@tonic-gate conjure_assert(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 852*7c478bd9Sstevel@tonic-gate { 853*7c478bd9Sstevel@tonic-gate assert(1 == 0); 854*7c478bd9Sstevel@tonic-gate return (NULL); 855*7c478bd9Sstevel@tonic-gate } 856*7c478bd9Sstevel@tonic-gate 857*7c478bd9Sstevel@tonic-gate static iidesc_t * 858*7c478bd9Sstevel@tonic-gate conjure_iidesc(iidesc_t *old, merge_cb_data_t *mcd) 859*7c478bd9Sstevel@tonic-gate { 860*7c478bd9Sstevel@tonic-gate iidesc_t *new = iidesc_dup(old); 861*7c478bd9Sstevel@tonic-gate int i; 862*7c478bd9Sstevel@tonic-gate 863*7c478bd9Sstevel@tonic-gate (void) remap_node(&new->ii_dtype, old->ii_dtype, -1, NULL, mcd); 864*7c478bd9Sstevel@tonic-gate for (i = 0; i < new->ii_nargs; i++) { 865*7c478bd9Sstevel@tonic-gate (void) remap_node(&new->ii_args[i], old->ii_args[i], -1, NULL, 866*7c478bd9Sstevel@tonic-gate mcd); 867*7c478bd9Sstevel@tonic-gate } 868*7c478bd9Sstevel@tonic-gate 869*7c478bd9Sstevel@tonic-gate return (new); 870*7c478bd9Sstevel@tonic-gate } 871*7c478bd9Sstevel@tonic-gate 872*7c478bd9Sstevel@tonic-gate static int 873*7c478bd9Sstevel@tonic-gate fwd_redir(tdesc_t *fwd, tdesc_t **fwdp, void *private) 874*7c478bd9Sstevel@tonic-gate { 875*7c478bd9Sstevel@tonic-gate alist_t *map = private; 876*7c478bd9Sstevel@tonic-gate tdesc_t *defn; 877*7c478bd9Sstevel@tonic-gate 878*7c478bd9Sstevel@tonic-gate if (!alist_find(map, (void *)fwd, (void **)&defn)) 879*7c478bd9Sstevel@tonic-gate return (0); 880*7c478bd9Sstevel@tonic-gate 881*7c478bd9Sstevel@tonic-gate debug(3, "Redirecting an edge to %s\n", 882*7c478bd9Sstevel@tonic-gate (defn->t_name ? defn->t_name : "(anon)")); 883*7c478bd9Sstevel@tonic-gate 884*7c478bd9Sstevel@tonic-gate *fwdp = defn; 885*7c478bd9Sstevel@tonic-gate 886*7c478bd9Sstevel@tonic-gate return (1); 887*7c478bd9Sstevel@tonic-gate } 888*7c478bd9Sstevel@tonic-gate 889*7c478bd9Sstevel@tonic-gate static tdtrav_cb_f fwd_redir_cbs[] = { 890*7c478bd9Sstevel@tonic-gate NULL, 891*7c478bd9Sstevel@tonic-gate NULL, /* intrinsic */ 892*7c478bd9Sstevel@tonic-gate NULL, /* pointer */ 893*7c478bd9Sstevel@tonic-gate NULL, /* array */ 894*7c478bd9Sstevel@tonic-gate NULL, /* function */ 895*7c478bd9Sstevel@tonic-gate NULL, /* struct */ 896*7c478bd9Sstevel@tonic-gate NULL, /* union */ 897*7c478bd9Sstevel@tonic-gate NULL, /* enum */ 898*7c478bd9Sstevel@tonic-gate fwd_redir, /* forward */ 899*7c478bd9Sstevel@tonic-gate NULL, /* typedef */ 900*7c478bd9Sstevel@tonic-gate tdtrav_assert, /* typedef_unres */ 901*7c478bd9Sstevel@tonic-gate NULL, /* volatile */ 902*7c478bd9Sstevel@tonic-gate NULL, /* const */ 903*7c478bd9Sstevel@tonic-gate NULL /* restrict */ 904*7c478bd9Sstevel@tonic-gate }; 905*7c478bd9Sstevel@tonic-gate 906*7c478bd9Sstevel@tonic-gate typedef struct redir_mstr_data { 907*7c478bd9Sstevel@tonic-gate tdata_t *rmd_tgt; 908*7c478bd9Sstevel@tonic-gate alist_t *rmd_map; 909*7c478bd9Sstevel@tonic-gate } redir_mstr_data_t; 910*7c478bd9Sstevel@tonic-gate 911*7c478bd9Sstevel@tonic-gate static int 912*7c478bd9Sstevel@tonic-gate redir_mstr_fwd_cb(void *name, void *value, void *arg) 913*7c478bd9Sstevel@tonic-gate { 914*7c478bd9Sstevel@tonic-gate tdesc_t *fwd = name; 915*7c478bd9Sstevel@tonic-gate int defnid = (int)value; 916*7c478bd9Sstevel@tonic-gate redir_mstr_data_t *rmd = arg; 917*7c478bd9Sstevel@tonic-gate tdesc_t template; 918*7c478bd9Sstevel@tonic-gate tdesc_t *defn; 919*7c478bd9Sstevel@tonic-gate 920*7c478bd9Sstevel@tonic-gate template.t_id = defnid; 921*7c478bd9Sstevel@tonic-gate 922*7c478bd9Sstevel@tonic-gate if (!hash_find(rmd->rmd_tgt->td_idhash, (void *)&template, 923*7c478bd9Sstevel@tonic-gate (void *)&defn)) { 924*7c478bd9Sstevel@tonic-gate terminate("Couldn't unforward %d (%s)\n", defnid, 925*7c478bd9Sstevel@tonic-gate (defn->t_name ? defn->t_name : "(anon)")); 926*7c478bd9Sstevel@tonic-gate } 927*7c478bd9Sstevel@tonic-gate 928*7c478bd9Sstevel@tonic-gate debug(3, "Forward map: resolved %d to %s\n", 929*7c478bd9Sstevel@tonic-gate defnid, (defn->t_name ? defn->t_name : "(anon)")); 930*7c478bd9Sstevel@tonic-gate 931*7c478bd9Sstevel@tonic-gate alist_add(rmd->rmd_map, (void *)fwd, (void *)defn); 932*7c478bd9Sstevel@tonic-gate 933*7c478bd9Sstevel@tonic-gate return (1); 934*7c478bd9Sstevel@tonic-gate } 935*7c478bd9Sstevel@tonic-gate 936*7c478bd9Sstevel@tonic-gate static void 937*7c478bd9Sstevel@tonic-gate redir_mstr_fwds(merge_cb_data_t *mcd) 938*7c478bd9Sstevel@tonic-gate { 939*7c478bd9Sstevel@tonic-gate redir_mstr_data_t rmd; 940*7c478bd9Sstevel@tonic-gate alist_t *map = alist_new(NULL, NULL); 941*7c478bd9Sstevel@tonic-gate 942*7c478bd9Sstevel@tonic-gate rmd.rmd_tgt = mcd->md_tgt; 943*7c478bd9Sstevel@tonic-gate rmd.rmd_map = map; 944*7c478bd9Sstevel@tonic-gate 945*7c478bd9Sstevel@tonic-gate if (alist_iter(mcd->md_fdida, redir_mstr_fwd_cb, &rmd)) { 946*7c478bd9Sstevel@tonic-gate (void) iitraverse_hash(mcd->md_tgt->td_iihash, 947*7c478bd9Sstevel@tonic-gate &mcd->md_tgt->td_curvgen, fwd_redir_cbs, NULL, NULL, map); 948*7c478bd9Sstevel@tonic-gate } 949*7c478bd9Sstevel@tonic-gate 950*7c478bd9Sstevel@tonic-gate alist_free(map); 951*7c478bd9Sstevel@tonic-gate } 952*7c478bd9Sstevel@tonic-gate 953*7c478bd9Sstevel@tonic-gate static int 954*7c478bd9Sstevel@tonic-gate add_iitba_cb(void *data, void *private) 955*7c478bd9Sstevel@tonic-gate { 956*7c478bd9Sstevel@tonic-gate merge_cb_data_t *mcd = private; 957*7c478bd9Sstevel@tonic-gate iidesc_t *tba = data; 958*7c478bd9Sstevel@tonic-gate iidesc_t *new; 959*7c478bd9Sstevel@tonic-gate iifind_data_t iif; 960*7c478bd9Sstevel@tonic-gate int newidx; 961*7c478bd9Sstevel@tonic-gate 962*7c478bd9Sstevel@tonic-gate newidx = get_mapping(mcd->md_ta, tba->ii_dtype->t_id); 963*7c478bd9Sstevel@tonic-gate assert(newidx != -1); 964*7c478bd9Sstevel@tonic-gate 965*7c478bd9Sstevel@tonic-gate (void) list_remove(mcd->md_iitba, data, NULL, NULL); 966*7c478bd9Sstevel@tonic-gate 967*7c478bd9Sstevel@tonic-gate iif.iif_template = tba; 968*7c478bd9Sstevel@tonic-gate iif.iif_ta = mcd->md_ta; 969*7c478bd9Sstevel@tonic-gate iif.iif_newidx = newidx; 970*7c478bd9Sstevel@tonic-gate iif.iif_refmerge = (mcd->md_flags & MCD_F_REFMERGE); 971*7c478bd9Sstevel@tonic-gate 972*7c478bd9Sstevel@tonic-gate if (hash_match(mcd->md_parent->td_iihash, tba, iidesc_match, 973*7c478bd9Sstevel@tonic-gate &iif) == 1) { 974*7c478bd9Sstevel@tonic-gate debug(3, "iidesc_t %s already exists\n", 975*7c478bd9Sstevel@tonic-gate (tba->ii_name ? tba->ii_name : "(anon)")); 976*7c478bd9Sstevel@tonic-gate return (1); 977*7c478bd9Sstevel@tonic-gate } 978*7c478bd9Sstevel@tonic-gate 979*7c478bd9Sstevel@tonic-gate new = conjure_iidesc(tba, mcd); 980*7c478bd9Sstevel@tonic-gate hash_add(mcd->md_tgt->td_iihash, new); 981*7c478bd9Sstevel@tonic-gate 982*7c478bd9Sstevel@tonic-gate return (1); 983*7c478bd9Sstevel@tonic-gate } 984*7c478bd9Sstevel@tonic-gate 985*7c478bd9Sstevel@tonic-gate static int 986*7c478bd9Sstevel@tonic-gate add_tdesc(tdesc_t *oldtdp, int newid, merge_cb_data_t *mcd) 987*7c478bd9Sstevel@tonic-gate { 988*7c478bd9Sstevel@tonic-gate tdesc_t *newtdp; 989*7c478bd9Sstevel@tonic-gate tdesc_t template; 990*7c478bd9Sstevel@tonic-gate 991*7c478bd9Sstevel@tonic-gate template.t_id = newid; 992*7c478bd9Sstevel@tonic-gate assert(hash_find(mcd->md_parent->td_idhash, 993*7c478bd9Sstevel@tonic-gate (void *)&template, NULL) == 0); 994*7c478bd9Sstevel@tonic-gate 995*7c478bd9Sstevel@tonic-gate debug(3, "trying to conjure %d %s (%d) as %d\n", 996*7c478bd9Sstevel@tonic-gate oldtdp->t_type, (oldtdp->t_name ? oldtdp->t_name : "(anon)"), 997*7c478bd9Sstevel@tonic-gate oldtdp->t_id, newid); 998*7c478bd9Sstevel@tonic-gate 999*7c478bd9Sstevel@tonic-gate if ((newtdp = tdesc_ops[oldtdp->t_type].conjure(oldtdp, newid, 1000*7c478bd9Sstevel@tonic-gate mcd)) == NULL) 1001*7c478bd9Sstevel@tonic-gate /* couldn't map everything */ 1002*7c478bd9Sstevel@tonic-gate return (0); 1003*7c478bd9Sstevel@tonic-gate 1004*7c478bd9Sstevel@tonic-gate debug(3, "succeeded\n"); 1005*7c478bd9Sstevel@tonic-gate 1006*7c478bd9Sstevel@tonic-gate hash_add(mcd->md_tgt->td_idhash, newtdp); 1007*7c478bd9Sstevel@tonic-gate hash_add(mcd->md_tgt->td_layouthash, newtdp); 1008*7c478bd9Sstevel@tonic-gate 1009*7c478bd9Sstevel@tonic-gate return (1); 1010*7c478bd9Sstevel@tonic-gate } 1011*7c478bd9Sstevel@tonic-gate 1012*7c478bd9Sstevel@tonic-gate static int 1013*7c478bd9Sstevel@tonic-gate add_tdtba_cb(void *data, void *arg) 1014*7c478bd9Sstevel@tonic-gate { 1015*7c478bd9Sstevel@tonic-gate tdesc_t *tdp = data; 1016*7c478bd9Sstevel@tonic-gate merge_cb_data_t *mcd = arg; 1017*7c478bd9Sstevel@tonic-gate int newid; 1018*7c478bd9Sstevel@tonic-gate int rc; 1019*7c478bd9Sstevel@tonic-gate 1020*7c478bd9Sstevel@tonic-gate newid = get_mapping(mcd->md_ta, tdp->t_id); 1021*7c478bd9Sstevel@tonic-gate assert(newid != -1); 1022*7c478bd9Sstevel@tonic-gate 1023*7c478bd9Sstevel@tonic-gate if ((rc = add_tdesc(tdp, newid, mcd))) 1024*7c478bd9Sstevel@tonic-gate hash_remove(mcd->md_tdtba, (void *)tdp); 1025*7c478bd9Sstevel@tonic-gate 1026*7c478bd9Sstevel@tonic-gate return (rc); 1027*7c478bd9Sstevel@tonic-gate } 1028*7c478bd9Sstevel@tonic-gate 1029*7c478bd9Sstevel@tonic-gate static int 1030*7c478bd9Sstevel@tonic-gate add_tdtbr_cb(void *data, void *arg) 1031*7c478bd9Sstevel@tonic-gate { 1032*7c478bd9Sstevel@tonic-gate tdesc_t **tdpp = data; 1033*7c478bd9Sstevel@tonic-gate merge_cb_data_t *mcd = arg; 1034*7c478bd9Sstevel@tonic-gate 1035*7c478bd9Sstevel@tonic-gate debug(3, "Remapping %s (%d)\n", 1036*7c478bd9Sstevel@tonic-gate ((*tdpp)->t_name ? (*tdpp)->t_name : "(anon)"), (*tdpp)->t_id); 1037*7c478bd9Sstevel@tonic-gate 1038*7c478bd9Sstevel@tonic-gate if (!remap_node(tdpp, *tdpp, -1, NULL, mcd)) 1039*7c478bd9Sstevel@tonic-gate return (0); 1040*7c478bd9Sstevel@tonic-gate 1041*7c478bd9Sstevel@tonic-gate (void) list_remove(mcd->md_tdtbr, (void *)tdpp, NULL, NULL); 1042*7c478bd9Sstevel@tonic-gate return (1); 1043*7c478bd9Sstevel@tonic-gate } 1044*7c478bd9Sstevel@tonic-gate 1045*7c478bd9Sstevel@tonic-gate static void 1046*7c478bd9Sstevel@tonic-gate merge_types(hash_t *src, merge_cb_data_t *mcd) 1047*7c478bd9Sstevel@tonic-gate { 1048*7c478bd9Sstevel@tonic-gate list_t *iitba = NULL; 1049*7c478bd9Sstevel@tonic-gate list_t *tdtbr = NULL; 1050*7c478bd9Sstevel@tonic-gate int iirc, tdrc; 1051*7c478bd9Sstevel@tonic-gate 1052*7c478bd9Sstevel@tonic-gate mcd->md_iitba = &iitba; 1053*7c478bd9Sstevel@tonic-gate mcd->md_tdtba = hash_new(TDATA_LAYOUT_HASH_SIZE, tdesc_layouthash, 1054*7c478bd9Sstevel@tonic-gate tdesc_layoutcmp); 1055*7c478bd9Sstevel@tonic-gate mcd->md_tdtbr = &tdtbr; 1056*7c478bd9Sstevel@tonic-gate 1057*7c478bd9Sstevel@tonic-gate (void) hash_iter(src, merge_type_cb, mcd); 1058*7c478bd9Sstevel@tonic-gate 1059*7c478bd9Sstevel@tonic-gate tdrc = hash_iter(mcd->md_tdtba, add_tdtba_cb, (void *)mcd); 1060*7c478bd9Sstevel@tonic-gate debug(3, "add_tdtba_cb added %d items\n", tdrc); 1061*7c478bd9Sstevel@tonic-gate 1062*7c478bd9Sstevel@tonic-gate iirc = list_iter(*mcd->md_iitba, add_iitba_cb, (void *)mcd); 1063*7c478bd9Sstevel@tonic-gate debug(3, "add_iitba_cb added %d items\n", iirc); 1064*7c478bd9Sstevel@tonic-gate 1065*7c478bd9Sstevel@tonic-gate assert(list_count(*mcd->md_iitba) == 0 && 1066*7c478bd9Sstevel@tonic-gate hash_count(mcd->md_tdtba) == 0); 1067*7c478bd9Sstevel@tonic-gate 1068*7c478bd9Sstevel@tonic-gate tdrc = list_iter(*mcd->md_tdtbr, add_tdtbr_cb, (void *)mcd); 1069*7c478bd9Sstevel@tonic-gate debug(3, "add_tdtbr_cb added %d items\n", tdrc); 1070*7c478bd9Sstevel@tonic-gate 1071*7c478bd9Sstevel@tonic-gate if (list_count(*mcd->md_tdtbr) != 0) 1072*7c478bd9Sstevel@tonic-gate terminate("Couldn't remap all nodes\n"); 1073*7c478bd9Sstevel@tonic-gate 1074*7c478bd9Sstevel@tonic-gate /* 1075*7c478bd9Sstevel@tonic-gate * We now have an alist of master forwards and the ids of the new master 1076*7c478bd9Sstevel@tonic-gate * definitions for those forwards in mcd->md_fdida. By this point, 1077*7c478bd9Sstevel@tonic-gate * we're guaranteed that all of the master definitions referenced in 1078*7c478bd9Sstevel@tonic-gate * fdida have been added to the master tree. We now traverse through 1079*7c478bd9Sstevel@tonic-gate * the master tree, redirecting all edges inbound to forwards that have 1080*7c478bd9Sstevel@tonic-gate * definitions to those definitions. 1081*7c478bd9Sstevel@tonic-gate */ 1082*7c478bd9Sstevel@tonic-gate if (mcd->md_parent == mcd->md_tgt) { 1083*7c478bd9Sstevel@tonic-gate redir_mstr_fwds(mcd); 1084*7c478bd9Sstevel@tonic-gate } 1085*7c478bd9Sstevel@tonic-gate } 1086*7c478bd9Sstevel@tonic-gate 1087*7c478bd9Sstevel@tonic-gate void 1088*7c478bd9Sstevel@tonic-gate merge_into_master(tdata_t *cur, tdata_t *mstr, tdata_t *tgt, int selfuniquify) 1089*7c478bd9Sstevel@tonic-gate { 1090*7c478bd9Sstevel@tonic-gate merge_cb_data_t mcd; 1091*7c478bd9Sstevel@tonic-gate 1092*7c478bd9Sstevel@tonic-gate cur->td_ref++; 1093*7c478bd9Sstevel@tonic-gate mstr->td_ref++; 1094*7c478bd9Sstevel@tonic-gate if (tgt) 1095*7c478bd9Sstevel@tonic-gate tgt->td_ref++; 1096*7c478bd9Sstevel@tonic-gate 1097*7c478bd9Sstevel@tonic-gate assert(cur->td_ref == 1 && mstr->td_ref == 1 && 1098*7c478bd9Sstevel@tonic-gate (tgt == NULL || tgt->td_ref == 1)); 1099*7c478bd9Sstevel@tonic-gate 1100*7c478bd9Sstevel@tonic-gate mcd.md_parent = mstr; 1101*7c478bd9Sstevel@tonic-gate mcd.md_tgt = (tgt ? tgt : mstr); 1102*7c478bd9Sstevel@tonic-gate mcd.md_ta = alist_new(NULL, NULL); 1103*7c478bd9Sstevel@tonic-gate mcd.md_fdida = alist_new(NULL, NULL); 1104*7c478bd9Sstevel@tonic-gate mcd.md_flags = 0; 1105*7c478bd9Sstevel@tonic-gate 1106*7c478bd9Sstevel@tonic-gate if (selfuniquify) 1107*7c478bd9Sstevel@tonic-gate mcd.md_flags |= MCD_F_SELFUNIQUIFY; 1108*7c478bd9Sstevel@tonic-gate if (tgt) 1109*7c478bd9Sstevel@tonic-gate mcd.md_flags |= MCD_F_REFMERGE; 1110*7c478bd9Sstevel@tonic-gate 1111*7c478bd9Sstevel@tonic-gate mstr->td_curvgen = MAX(mstr->td_curvgen, cur->td_curvgen); 1112*7c478bd9Sstevel@tonic-gate mstr->td_curemark = MAX(mstr->td_curemark, cur->td_curemark); 1113*7c478bd9Sstevel@tonic-gate 1114*7c478bd9Sstevel@tonic-gate merge_types(cur->td_iihash, &mcd); 1115*7c478bd9Sstevel@tonic-gate 1116*7c478bd9Sstevel@tonic-gate if (debug_level >= 3) { 1117*7c478bd9Sstevel@tonic-gate debug(3, "Type association stats\n"); 1118*7c478bd9Sstevel@tonic-gate alist_stats(mcd.md_ta, 0); 1119*7c478bd9Sstevel@tonic-gate debug(3, "Layout hash stats\n"); 1120*7c478bd9Sstevel@tonic-gate hash_stats(mcd.md_tgt->td_layouthash, 1); 1121*7c478bd9Sstevel@tonic-gate } 1122*7c478bd9Sstevel@tonic-gate 1123*7c478bd9Sstevel@tonic-gate alist_free(mcd.md_fdida); 1124*7c478bd9Sstevel@tonic-gate alist_free(mcd.md_ta); 1125*7c478bd9Sstevel@tonic-gate 1126*7c478bd9Sstevel@tonic-gate cur->td_ref--; 1127*7c478bd9Sstevel@tonic-gate mstr->td_ref--; 1128*7c478bd9Sstevel@tonic-gate if (tgt) 1129*7c478bd9Sstevel@tonic-gate tgt->td_ref--; 1130*7c478bd9Sstevel@tonic-gate } 1131*7c478bd9Sstevel@tonic-gate 1132*7c478bd9Sstevel@tonic-gate tdesc_ops_t tdesc_ops[] = { 1133*7c478bd9Sstevel@tonic-gate { "ERROR! BAD tdesc TYPE", NULL, NULL }, 1134*7c478bd9Sstevel@tonic-gate { "intrinsic", equiv_intrinsic, conjure_intrinsic }, 1135*7c478bd9Sstevel@tonic-gate { "pointer", equiv_plain, conjure_plain }, 1136*7c478bd9Sstevel@tonic-gate { "array", equiv_array, conjure_array }, 1137*7c478bd9Sstevel@tonic-gate { "function", equiv_function, conjure_function }, 1138*7c478bd9Sstevel@tonic-gate { "struct", equiv_su, conjure_su }, 1139*7c478bd9Sstevel@tonic-gate { "union", equiv_su, conjure_su }, 1140*7c478bd9Sstevel@tonic-gate { "enum", equiv_enum, conjure_enum }, 1141*7c478bd9Sstevel@tonic-gate { "forward", NULL, conjure_forward }, 1142*7c478bd9Sstevel@tonic-gate { "typedef", equiv_plain, conjure_plain }, 1143*7c478bd9Sstevel@tonic-gate { "typedef_unres", equiv_assert, conjure_assert }, 1144*7c478bd9Sstevel@tonic-gate { "volatile", equiv_plain, conjure_plain }, 1145*7c478bd9Sstevel@tonic-gate { "const", equiv_plain, conjure_plain }, 1146*7c478bd9Sstevel@tonic-gate { "restrict", equiv_plain, conjure_plain } 1147*7c478bd9Sstevel@tonic-gate }; 1148