Print this page
    
12259 CTF shouldn't assume enum size
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/lib/libctf/common/ctf_merge.c
          +++ new/usr/src/lib/libctf/common/ctf_merge.c
   1    1  /*
   2    2   * This file and its contents are supplied under the terms of the
  
    | 
      ↓ open down ↓ | 
    2 lines elided | 
    
      ↑ open up ↑ | 
  
   3    3   * Common Development and Distribution License ("CDDL"), version 1.0.
   4    4   * You may only use this file in accordance with the terms of version
   5    5   * 1.0 of the CDDL.
   6    6   *
   7    7   * A full copy of the text of the CDDL should have accompanied this
   8    8   * source.  A copy of the CDDL is also available via the Internet at
   9    9   * http://www.illumos.org/license/CDDL.
  10   10   */
  11   11  
  12   12  /*
  13      - * Copyright 2019, Joyent, Inc.
       13 + * Copyright 2020 Joyent, Inc.
  14   14   */
  15   15  
  16   16  /*
  17   17   * To perform a merge of two CTF containers, we first diff the two containers
  18   18   * types. For every type that's in the src container, but not in the dst
  19   19   * container, we note it and add it to dst container. If there are any objects
  20   20   * or functions associated with src, we go through and update the types that
  21   21   * they refer to such that they all refer to types in the dst container.
  22   22   *
  23   23   * The bulk of the logic for the merge, after we've run the diff, occurs in
  24   24   * ctf_merge_common().
  25   25   *
  26   26   * In terms of exported APIs, we don't really export a simple merge two
  27   27   * containers, as the general way this is used, in something like ctfmerge(1),
  28   28   * is to add all the containers and then let us figure out the best way to merge
  29   29   * it.
  30   30   */
  31   31  
  32   32  #include <libctf_impl.h>
  33   33  #include <sys/debug.h>
  34   34  #include <sys/list.h>
  35   35  #include <stddef.h>
  36   36  #include <fcntl.h>
  37   37  #include <sys/types.h>
  38   38  #include <sys/stat.h>
  39   39  #include <mergeq.h>
  40   40  #include <errno.h>
  41   41  
  42   42  typedef struct ctf_merge_tinfo {
  43   43          uint16_t cmt_map;       /* Map to the type in out */
  44   44          boolean_t cmt_fixup;
  45   45          boolean_t cmt_forward;
  46   46          boolean_t cmt_missing;
  47   47  } ctf_merge_tinfo_t;
  48   48  
  49   49  /*
  50   50   * State required for doing an individual merge of two containers.
  51   51   */
  52   52  typedef struct ctf_merge_types {
  53   53          ctf_file_t *cm_out;             /* Output CTF file */
  54   54          ctf_file_t *cm_src;             /* Input CTF file */
  55   55          ctf_merge_tinfo_t *cm_tmap;     /* Type state information */
  56   56          boolean_t cm_dedup;             /* Are we doing a dedup? */
  57   57          boolean_t cm_unique;            /* are we doing a uniquify? */
  58   58  } ctf_merge_types_t;
  59   59  
  60   60  typedef struct ctf_merge_objmap {
  61   61          list_node_t cmo_node;
  62   62          const char *cmo_name;           /* Symbol name */
  63   63          const char *cmo_file;           /* Symbol file */
  64   64          ulong_t cmo_idx;                /* Symbol ID */
  65   65          Elf64_Sym cmo_sym;              /* Symbol Entry */
  66   66          ctf_id_t cmo_tid;               /* Type ID */
  67   67  } ctf_merge_objmap_t;
  68   68  
  69   69  typedef struct ctf_merge_funcmap {
  70   70          list_node_t cmf_node;
  71   71          const char *cmf_name;           /* Symbol name */
  72   72          const char *cmf_file;           /* Symbol file */
  73   73          ulong_t cmf_idx;                /* Symbol ID */
  74   74          Elf64_Sym cmf_sym;              /* Symbol Entry */
  75   75          ctf_id_t cmf_rtid;              /* Type ID */
  76   76          uint_t cmf_flags;               /* ctf_funcinfo_t ctc_flags */
  77   77          uint_t cmf_argc;                /* Number of arguments */
  78   78          ctf_id_t cmf_args[];            /* Types of arguments */
  79   79  } ctf_merge_funcmap_t;
  80   80  
  81   81  typedef struct ctf_merge_input {
  82   82          list_node_t cmi_node;
  83   83          ctf_file_t *cmi_input;
  84   84          list_t cmi_omap;
  85   85          list_t cmi_fmap;
  86   86          boolean_t cmi_created;
  87   87  } ctf_merge_input_t;
  88   88  
  89   89  struct ctf_merge_handle {
  90   90          list_t cmh_inputs;              /* Input list */
  91   91          uint_t cmh_ninputs;             /* Number of inputs */
  92   92          uint_t cmh_nthreads;            /* Number of threads to use */
  93   93          ctf_file_t *cmh_unique;         /* ctf to uniquify against */
  94   94          boolean_t cmh_msyms;            /* Should we merge symbols/funcs? */
  95   95          int cmh_ofd;                    /* FD for output file */
  96   96          int cmh_flags;                  /* Flags that control merge behavior */
  97   97          char *cmh_label;                /* Optional label */
  98   98          char *cmh_pname;                /* Parent name */
  99   99  };
 100  100  
 101  101  typedef struct ctf_merge_symbol_arg {
 102  102          list_t *cmsa_objmap;
 103  103          list_t *cmsa_funcmap;
 104  104          ctf_file_t *cmsa_out;
 105  105          boolean_t cmsa_dedup;
 106  106  } ctf_merge_symbol_arg_t;
 107  107  
 108  108  static int ctf_merge_add_type(ctf_merge_types_t *, ctf_id_t);
 109  109  
 110  110  static ctf_id_t
 111  111  ctf_merge_gettype(ctf_merge_types_t *cmp, ctf_id_t id)
 112  112  {
 113  113          if (cmp->cm_dedup == B_FALSE) {
 114  114                  VERIFY(cmp->cm_tmap[id].cmt_map != 0);
 115  115                  return (cmp->cm_tmap[id].cmt_map);
 116  116          }
 117  117  
 118  118          while (cmp->cm_tmap[id].cmt_missing == B_FALSE) {
 119  119                  VERIFY(cmp->cm_tmap[id].cmt_map != 0);
 120  120                  id = cmp->cm_tmap[id].cmt_map;
 121  121          }
 122  122          VERIFY(cmp->cm_tmap[id].cmt_map != 0);
 123  123          return (cmp->cm_tmap[id].cmt_map);
 124  124  }
 125  125  
 126  126  static void
 127  127  ctf_merge_diffcb(ctf_file_t *ifp, ctf_id_t iid, boolean_t same, ctf_file_t *ofp,
 128  128      ctf_id_t oid, void *arg)
 129  129  {
 130  130          ctf_merge_types_t *cmp = arg;
 131  131          ctf_merge_tinfo_t *cmt = cmp->cm_tmap;
 132  132  
 133  133          if (same == B_TRUE) {
 134  134                  if (ctf_type_kind(ifp, iid) == CTF_K_FORWARD &&
 135  135                      ctf_type_kind(ofp, oid) != CTF_K_FORWARD) {
 136  136                          VERIFY(cmt[oid].cmt_map == 0);
 137  137  
 138  138                          /*
 139  139                           * If we're uniquifying types, it's possible for the
 140  140                           * container that we're uniquifying against to have a
 141  141                           * forward which exists in the container being reduced.
 142  142                           * For example, genunix has the machcpu structure as a
 143  143                           * forward which is actually in unix and we uniquify
 144  144                           * unix against genunix. In such cases, we explicitly do
 145  145                           * not do any mapping of the forward information, lest
 146  146                           * we risk losing the real definition. Instead, mark
 147  147                           * that it's missing.
 148  148                           */
 149  149                          if (cmp->cm_unique == B_TRUE) {
 150  150                                  cmt[oid].cmt_missing = B_TRUE;
 151  151                                  return;
 152  152                          }
 153  153  
 154  154                          cmt[oid].cmt_map = iid;
 155  155                          cmt[oid].cmt_forward = B_TRUE;
 156  156                          ctf_dprintf("merge diff forward mapped %d->%d\n", oid,
 157  157                              iid);
 158  158                          return;
 159  159                  }
 160  160  
 161  161                  /*
 162  162                   * We could have multiple things that a given type ends up
 163  163                   * matching in the world of forwards and pointers to forwards.
 164  164                   * For now just take the first one...
 165  165                   */
 166  166                  if (cmt[oid].cmt_map != 0)
 167  167                          return;
 168  168                  cmt[oid].cmt_map = iid;
 169  169                  ctf_dprintf("merge diff mapped %d->%d\n", oid, iid);
 170  170          } else if (ifp == cmp->cm_src) {
 171  171                  VERIFY(cmt[iid].cmt_map == 0);
 172  172                  cmt[iid].cmt_missing = B_TRUE;
 173  173                  ctf_dprintf("merge diff said %d is missing\n", iid);
 174  174          }
 175  175  }
 176  176  
 177  177  static int
 178  178  ctf_merge_add_number(ctf_merge_types_t *cmp, ctf_id_t id)
 179  179  {
 180  180          int ret, flags;
 181  181          const ctf_type_t *tp;
 182  182          const char *name;
 183  183          ctf_encoding_t en;
 184  184  
 185  185          if (ctf_type_encoding(cmp->cm_src, id, &en) != 0)
 186  186                  return (CTF_ERR);
 187  187  
 188  188          tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
 189  189          name = ctf_strraw(cmp->cm_src, tp->ctt_name);
 190  190          if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
 191  191                  flags = CTF_ADD_ROOT;
 192  192          else
 193  193                  flags = CTF_ADD_NONROOT;
 194  194  
 195  195          ret = ctf_add_encoded(cmp->cm_out, flags, name, &en,
 196  196              ctf_type_kind(cmp->cm_src, id));
 197  197  
 198  198          if (ret == CTF_ERR)
 199  199                  return (ret);
 200  200  
 201  201          VERIFY(cmp->cm_tmap[id].cmt_map == 0);
 202  202          cmp->cm_tmap[id].cmt_map = ret;
 203  203          return (0);
 204  204  }
 205  205  
 206  206  static int
 207  207  ctf_merge_add_array(ctf_merge_types_t *cmp, ctf_id_t id)
 208  208  {
 209  209          int ret, flags;
 210  210          const ctf_type_t *tp;
 211  211          ctf_arinfo_t ar;
 212  212  
 213  213          if (ctf_array_info(cmp->cm_src, id, &ar) == CTF_ERR)
 214  214                  return (CTF_ERR);
 215  215  
 216  216          tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
 217  217          if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
 218  218                  flags = CTF_ADD_ROOT;
 219  219          else
 220  220                  flags = CTF_ADD_NONROOT;
 221  221  
 222  222          if (cmp->cm_tmap[ar.ctr_contents].cmt_map == 0) {
 223  223                  ret = ctf_merge_add_type(cmp, ar.ctr_contents);
 224  224                  if (ret != 0)
 225  225                          return (ret);
 226  226                  ASSERT(cmp->cm_tmap[ar.ctr_contents].cmt_map != 0);
 227  227          }
 228  228          ar.ctr_contents = ctf_merge_gettype(cmp, ar.ctr_contents);
 229  229  
 230  230          if (cmp->cm_tmap[ar.ctr_index].cmt_map == 0) {
 231  231                  ret = ctf_merge_add_type(cmp, ar.ctr_index);
 232  232                  if (ret != 0)
 233  233                          return (ret);
 234  234                  ASSERT(cmp->cm_tmap[ar.ctr_index].cmt_map != 0);
 235  235          }
 236  236          ar.ctr_index = ctf_merge_gettype(cmp, ar.ctr_index);
 237  237  
 238  238          ret = ctf_add_array(cmp->cm_out, flags, &ar);
 239  239          if (ret == CTF_ERR)
 240  240                  return (ret);
 241  241  
 242  242          VERIFY(cmp->cm_tmap[id].cmt_map == 0);
 243  243          cmp->cm_tmap[id].cmt_map = ret;
 244  244  
 245  245          return (0);
 246  246  }
 247  247  
 248  248  static int
 249  249  ctf_merge_add_reftype(ctf_merge_types_t *cmp, ctf_id_t id)
 250  250  {
 251  251          int ret, flags;
 252  252          const ctf_type_t *tp;
 253  253          ctf_id_t reftype;
 254  254          const char *name;
 255  255  
 256  256          tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
 257  257          name = ctf_strraw(cmp->cm_src, tp->ctt_name);
 258  258          if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
 259  259                  flags = CTF_ADD_ROOT;
 260  260          else
 261  261                  flags = CTF_ADD_NONROOT;
 262  262  
 263  263          reftype = ctf_type_reference(cmp->cm_src, id);
 264  264          if (reftype == CTF_ERR)
 265  265                  return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src)));
 266  266  
 267  267          if (cmp->cm_tmap[reftype].cmt_map == 0) {
 268  268                  ret = ctf_merge_add_type(cmp, reftype);
 269  269                  if (ret != 0)
 270  270                          return (ret);
 271  271                  ASSERT(cmp->cm_tmap[reftype].cmt_map != 0);
 272  272          }
 273  273          reftype = ctf_merge_gettype(cmp, reftype);
 274  274  
 275  275          ret = ctf_add_reftype(cmp->cm_out, flags, name, reftype,
 276  276              ctf_type_kind(cmp->cm_src, id));
 277  277          if (ret == CTF_ERR)
 278  278                  return (ret);
 279  279  
 280  280          VERIFY(cmp->cm_tmap[id].cmt_map == 0);
 281  281          cmp->cm_tmap[id].cmt_map = ret;
 282  282          return (0);
 283  283  }
 284  284  
 285  285  static int
 286  286  ctf_merge_add_typedef(ctf_merge_types_t *cmp, ctf_id_t id)
 287  287  {
 288  288          int ret, flags;
 289  289          const ctf_type_t *tp;
 290  290          const char *name;
 291  291          ctf_id_t reftype;
 292  292  
 293  293          tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
 294  294          name = ctf_strraw(cmp->cm_src, tp->ctt_name);
 295  295          if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
 296  296                  flags = CTF_ADD_ROOT;
 297  297          else
 298  298                  flags = CTF_ADD_NONROOT;
 299  299  
 300  300          reftype = ctf_type_reference(cmp->cm_src, id);
 301  301          if (reftype == CTF_ERR)
 302  302                  return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src)));
 303  303  
 304  304          if (cmp->cm_tmap[reftype].cmt_map == 0) {
 305  305                  ret = ctf_merge_add_type(cmp, reftype);
 306  306                  if (ret != 0)
 307  307                          return (ret);
 308  308                  ASSERT(cmp->cm_tmap[reftype].cmt_map != 0);
 309  309          }
 310  310          reftype = ctf_merge_gettype(cmp, reftype);
 311  311  
 312  312          ret = ctf_add_typedef(cmp->cm_out, flags, name, reftype);
 313  313          if (ret == CTF_ERR)
 314  314                  return (ret);
 315  315  
 316  316          VERIFY(cmp->cm_tmap[id].cmt_map == 0);
 317  317          cmp->cm_tmap[id].cmt_map = ret;
 318  318          return (0);
 319  319  }
 320  320  
 321  321  typedef struct ctf_merge_enum {
 322  322          ctf_file_t *cme_fp;
 323  323          ctf_id_t cme_id;
 324  324  } ctf_merge_enum_t;
 325  325  
 326  326  static int
 327  327  ctf_merge_add_enumerator(const char *name, int value, void *arg)
 328  328  {
 329  329          ctf_merge_enum_t *cmep = arg;
 330  330  
 331  331          return (ctf_add_enumerator(cmep->cme_fp, cmep->cme_id, name, value) ==
 332  332              CTF_ERR);
  
    | 
      ↓ open down ↓ | 
    309 lines elided | 
    
      ↑ open up ↑ | 
  
 333  333  }
 334  334  
 335  335  static int
 336  336  ctf_merge_add_enum(ctf_merge_types_t *cmp, ctf_id_t id)
 337  337  {
 338  338          int flags;
 339  339          const ctf_type_t *tp;
 340  340          const char *name;
 341  341          ctf_id_t enumid;
 342  342          ctf_merge_enum_t cme;
      343 +        size_t size;
 343  344  
 344  345          tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
 345      -        name = ctf_strraw(cmp->cm_src, tp->ctt_name);
 346  346          if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
 347  347                  flags = CTF_ADD_ROOT;
 348  348          else
 349  349                  flags = CTF_ADD_NONROOT;
 350  350  
 351      -        enumid = ctf_add_enum(cmp->cm_out, flags, name);
      351 +        name = ctf_strraw(cmp->cm_src, tp->ctt_name);
      352 +        size = ctf_get_ctt_size(cmp->cm_src, tp, NULL, NULL);
      353 +
      354 +        enumid = ctf_add_enum(cmp->cm_out, flags, name, size);
 352  355          if (enumid == CTF_ERR)
 353  356                  return (enumid);
 354  357  
 355  358          cme.cme_fp = cmp->cm_out;
 356  359          cme.cme_id = enumid;
 357  360          if (ctf_enum_iter(cmp->cm_src, id, ctf_merge_add_enumerator,
 358  361              &cme) != 0)
 359  362                  return (CTF_ERR);
 360  363  
 361  364          VERIFY(cmp->cm_tmap[id].cmt_map == 0);
 362  365          cmp->cm_tmap[id].cmt_map = enumid;
 363  366          return (0);
 364  367  }
 365  368  
 366  369  static int
 367  370  ctf_merge_add_func(ctf_merge_types_t *cmp, ctf_id_t id)
 368  371  {
 369  372          int ret, flags, i;
 370  373          const ctf_type_t *tp;
 371  374          ctf_funcinfo_t ctc;
 372  375          ctf_id_t *argv;
 373  376  
 374  377          tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
 375  378          if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
 376  379                  flags = CTF_ADD_ROOT;
 377  380          else
 378  381                  flags = CTF_ADD_NONROOT;
 379  382  
 380  383          if (ctf_func_info_by_id(cmp->cm_src, id, &ctc) == CTF_ERR)
 381  384                  return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src)));
 382  385  
 383  386          argv = ctf_alloc(sizeof (ctf_id_t) * ctc.ctc_argc);
 384  387          if (argv == NULL)
 385  388                  return (ctf_set_errno(cmp->cm_out, ENOMEM));
 386  389          if (ctf_func_args_by_id(cmp->cm_src, id, ctc.ctc_argc, argv) ==
 387  390              CTF_ERR) {
 388  391                  ctf_free(argv, sizeof (ctf_id_t) * ctc.ctc_argc);
 389  392                  return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src)));
 390  393          }
 391  394  
 392  395          if (cmp->cm_tmap[ctc.ctc_return].cmt_map == 0) {
 393  396                  ret = ctf_merge_add_type(cmp, ctc.ctc_return);
 394  397                  if (ret != 0)
 395  398                          return (ret);
 396  399                  ASSERT(cmp->cm_tmap[ctc.ctc_return].cmt_map != 0);
 397  400          }
 398  401          ctc.ctc_return = ctf_merge_gettype(cmp, ctc.ctc_return);
 399  402  
 400  403          for (i = 0; i < ctc.ctc_argc; i++) {
 401  404                  if (cmp->cm_tmap[argv[i]].cmt_map == 0) {
 402  405                          ret = ctf_merge_add_type(cmp, argv[i]);
 403  406                          if (ret != 0)
 404  407                                  return (ret);
 405  408                          ASSERT(cmp->cm_tmap[argv[i]].cmt_map != 0);
 406  409                  }
 407  410                  argv[i] = ctf_merge_gettype(cmp, argv[i]);
 408  411          }
 409  412  
 410  413          ret = ctf_add_funcptr(cmp->cm_out, flags, &ctc, argv);
 411  414          ctf_free(argv, sizeof (ctf_id_t) * ctc.ctc_argc);
 412  415          if (ret == CTF_ERR)
 413  416                  return (ret);
 414  417  
 415  418          VERIFY(cmp->cm_tmap[id].cmt_map == 0);
 416  419          cmp->cm_tmap[id].cmt_map = ret;
 417  420          return (0);
 418  421  }
 419  422  
 420  423  static int
 421  424  ctf_merge_add_forward(ctf_merge_types_t *cmp, ctf_id_t id)
 422  425  {
 423  426          int ret, flags;
 424  427          const ctf_type_t *tp;
 425  428          const char *name;
 426  429  
 427  430          tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
 428  431          name = ctf_strraw(cmp->cm_src, tp->ctt_name);
 429  432          if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
 430  433                  flags = CTF_ADD_ROOT;
 431  434          else
 432  435                  flags = CTF_ADD_NONROOT;
 433  436  
 434  437          /*
 435  438           * ctf_add_forward tries to check to see if a given forward already
 436  439           * exists in one of its hash tables.  If we're here then we know that we
 437  440           * have a forward in a container that isn't present in another.
 438  441           * Therefore, we choose a token hash table to satisfy the API choice
 439  442           * here.
 440  443           */
 441  444          ret = ctf_add_forward(cmp->cm_out, flags, name, CTF_K_STRUCT);
 442  445          if (ret == CTF_ERR)
 443  446                  return (CTF_ERR);
 444  447  
 445  448          VERIFY(cmp->cm_tmap[id].cmt_map == 0);
 446  449          cmp->cm_tmap[id].cmt_map = ret;
 447  450          return (0);
 448  451  }
 449  452  
 450  453  typedef struct ctf_merge_su {
 451  454          ctf_merge_types_t *cms_cm;
 452  455          ctf_id_t cms_id;
 453  456  } ctf_merge_su_t;
 454  457  
 455  458  static int
 456  459  ctf_merge_add_member(const char *name, ctf_id_t type, ulong_t offset, void *arg)
 457  460  {
 458  461          ctf_merge_su_t *cms = arg;
 459  462  
 460  463          VERIFY(cms->cms_cm->cm_tmap[type].cmt_map != 0);
 461  464          type = cms->cms_cm->cm_tmap[type].cmt_map;
 462  465  
 463  466          ctf_dprintf("Trying to add member %s to %d\n", name, cms->cms_id);
 464  467          return (ctf_add_member(cms->cms_cm->cm_out, cms->cms_id, name,
 465  468              type, offset) == CTF_ERR);
 466  469  }
 467  470  
 468  471  /*
 469  472   * During the first pass, we always add the generic structure and union but none
 470  473   * of its members as they might not all have been mapped yet. Instead we just
 471  474   * mark all structures and unions as needing to be fixed up.
 472  475   */
 473  476  static int
 474  477  ctf_merge_add_sou(ctf_merge_types_t *cmp, ctf_id_t id, boolean_t forward)
 475  478  {
 476  479          int flags, kind;
 477  480          const ctf_type_t *tp;
 478  481          const char *name;
 479  482          ctf_id_t suid;
 480  483  
 481  484          tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
 482  485          name = ctf_strraw(cmp->cm_src, tp->ctt_name);
 483  486          if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
 484  487                  flags = CTF_ADD_ROOT;
 485  488          else
 486  489                  flags = CTF_ADD_NONROOT;
 487  490          kind = ctf_type_kind(cmp->cm_src, id);
 488  491  
 489  492          if (kind == CTF_K_STRUCT)
 490  493                  suid = ctf_add_struct(cmp->cm_out, flags, name);
 491  494          else
 492  495                  suid = ctf_add_union(cmp->cm_out, flags, name);
 493  496  
 494  497          if (suid == CTF_ERR)
 495  498                  return (suid);
 496  499  
 497  500          /*
 498  501           * If this is a forward reference then its mapping should already
 499  502           * exist.
 500  503           */
 501  504          if (forward == B_FALSE) {
 502  505                  VERIFY(cmp->cm_tmap[id].cmt_map == 0);
 503  506                  cmp->cm_tmap[id].cmt_map = suid;
 504  507                  ctf_dprintf("added sou \"%s\" as (%d) %d->%d\n", name, kind, id,
 505  508                      suid);
 506  509          } else {
 507  510                  VERIFY(cmp->cm_tmap[id].cmt_map == suid);
 508  511          }
 509  512          cmp->cm_tmap[id].cmt_fixup = B_TRUE;
 510  513  
 511  514          return (0);
 512  515  }
 513  516  
 514  517  static int
 515  518  ctf_merge_add_type(ctf_merge_types_t *cmp, ctf_id_t id)
 516  519  {
 517  520          int kind, ret;
 518  521  
 519  522          /*
 520  523           * We may end up evaluating a type more than once as we may deal with it
 521  524           * as we recursively evaluate some kind of reference and then we may see
 522  525           * it normally.
 523  526           */
 524  527          if (cmp->cm_tmap[id].cmt_map != 0)
 525  528                  return (0);
 526  529  
 527  530          kind = ctf_type_kind(cmp->cm_src, id);
 528  531          switch (kind) {
 529  532          case CTF_K_INTEGER:
 530  533          case CTF_K_FLOAT:
 531  534                  ret = ctf_merge_add_number(cmp, id);
 532  535                  break;
 533  536          case CTF_K_ARRAY:
 534  537                  ret = ctf_merge_add_array(cmp, id);
 535  538                  break;
 536  539          case CTF_K_POINTER:
 537  540          case CTF_K_VOLATILE:
 538  541          case CTF_K_CONST:
 539  542          case CTF_K_RESTRICT:
 540  543                  ret = ctf_merge_add_reftype(cmp, id);
 541  544                  break;
 542  545          case CTF_K_TYPEDEF:
 543  546                  ret = ctf_merge_add_typedef(cmp, id);
 544  547                  break;
 545  548          case CTF_K_ENUM:
 546  549                  ret = ctf_merge_add_enum(cmp, id);
 547  550                  break;
 548  551          case CTF_K_FUNCTION:
 549  552                  ret = ctf_merge_add_func(cmp, id);
 550  553                  break;
 551  554          case CTF_K_FORWARD:
 552  555                  ret = ctf_merge_add_forward(cmp, id);
 553  556                  break;
 554  557          case CTF_K_STRUCT:
 555  558          case CTF_K_UNION:
 556  559                  ret = ctf_merge_add_sou(cmp, id, B_FALSE);
 557  560                  break;
 558  561          case CTF_K_UNKNOWN:
 559  562                  /*
 560  563                   * We don't add unknown types, and we later assert that nothing
 561  564                   * should reference them.
 562  565                   */
 563  566                  return (0);
 564  567          default:
 565  568                  abort();
 566  569          }
 567  570  
 568  571          return (ret);
 569  572  }
 570  573  
 571  574  static int
 572  575  ctf_merge_fixup_sou(ctf_merge_types_t *cmp, ctf_id_t id)
 573  576  {
 574  577          ctf_dtdef_t *dtd;
 575  578          ctf_merge_su_t cms;
 576  579          ctf_id_t mapid;
 577  580          ssize_t size;
 578  581  
 579  582          mapid = cmp->cm_tmap[id].cmt_map;
 580  583          VERIFY(mapid != 0);
 581  584          dtd = ctf_dtd_lookup(cmp->cm_out, mapid);
 582  585          VERIFY(dtd != NULL);
 583  586  
 584  587          ctf_dprintf("Trying to fix up sou %d\n", id);
 585  588          cms.cms_cm = cmp;
 586  589          cms.cms_id = mapid;
 587  590          if (ctf_member_iter(cmp->cm_src, id, ctf_merge_add_member, &cms) != 0)
 588  591                  return (CTF_ERR);
 589  592  
 590  593          if ((size = ctf_type_size(cmp->cm_src, id)) == CTF_ERR)
 591  594                  return (CTF_ERR);
 592  595          if (ctf_set_size(cmp->cm_out, mapid, size) == CTF_ERR)
 593  596                  return (CTF_ERR);
 594  597  
 595  598          return (0);
 596  599  }
 597  600  
 598  601  static int
 599  602  ctf_merge_fixup_type(ctf_merge_types_t *cmp, ctf_id_t id)
 600  603  {
 601  604          int kind, ret;
 602  605  
 603  606          kind = ctf_type_kind(cmp->cm_src, id);
 604  607          switch (kind) {
 605  608          case CTF_K_STRUCT:
 606  609          case CTF_K_UNION:
 607  610                  ret = ctf_merge_fixup_sou(cmp, id);
 608  611                  break;
 609  612          default:
 610  613                  VERIFY(0);
 611  614                  ret = CTF_ERR;
 612  615          }
 613  616  
 614  617          return (ret);
 615  618  }
 616  619  
 617  620  /*
 618  621   * Now that we've successfully merged everything, we're going to remap the type
 619  622   * table.
 620  623   *
 621  624   * Remember we have two containers: ->cm_src is what we're working from, and
 622  625   * ->cm_out is where we are building the de-duplicated CTF.
 623  626   *
 624  627   * The index of this table is always the type IDs in ->cm_src.
 625  628   *
 626  629   * When we built this table originally in ctf_diff_self(), if we found a novel
 627  630   * type, we marked it as .cmt_missing to indicate it needs adding to ->cm_out.
 628  631   * Otherwise, .cmt_map indicated the ->cm_src type ID that this type duplicates.
 629  632   *
 630  633   * Then, in ctf_merge_common(), we walked through and added all "cmt_missing"
 631  634   * types to ->cm_out with ctf_merge_add_type(). These routines update cmt_map
 632  635   * to be the *new* type ID in ->cm_out.  In this function, you can read
 633  636   * "cmt_missing" as meaning "added to ->cm_out, and cmt_map updated".
 634  637   *
 635  638   * So at this point, we need to mop up all types where .cmt_missing == B_FALSE,
 636  639   * making sure *their* .cmt_map values also point to the ->cm_out container.
 637  640   */
 638  641  static void
 639  642  ctf_merge_dedup_remap(ctf_merge_types_t *cmp)
 640  643  {
 641  644          int i;
 642  645  
 643  646          for (i = 1; i < cmp->cm_src->ctf_typemax + 1; i++) {
 644  647                  ctf_id_t tid;
 645  648  
 646  649                  if (cmp->cm_tmap[i].cmt_missing == B_TRUE) {
 647  650                          VERIFY(cmp->cm_tmap[i].cmt_map != 0);
 648  651                          continue;
 649  652                  }
 650  653  
 651  654                  tid = i;
 652  655                  while (cmp->cm_tmap[tid].cmt_missing == B_FALSE) {
 653  656                          VERIFY(cmp->cm_tmap[tid].cmt_map != 0);
 654  657                          tid = cmp->cm_tmap[tid].cmt_map;
 655  658                  }
 656  659                  VERIFY(cmp->cm_tmap[tid].cmt_map != 0);
 657  660                  cmp->cm_tmap[i].cmt_map = cmp->cm_tmap[tid].cmt_map;
 658  661          }
 659  662  }
 660  663  
 661  664  
 662  665  /*
 663  666   * We're going to do three passes over the containers.
 664  667   *
 665  668   * Pass 1 checks for forward references in the output container that we know
 666  669   * exist in the source container.
 667  670   *
 668  671   * Pass 2 adds all the missing types from the source container. As part of this
 669  672   * we may be adding a type as a forward reference that doesn't exist yet.
 670  673   * Any types that we encounter in this form, we need to add to a third pass.
 671  674   *
 672  675   * Pass 3 is the fixup pass. Here we go through and find all the types that were
 673  676   * missing in the first.
 674  677   *
 675  678   * Importantly, we *must* call ctf_update between the second and third pass,
 676  679   * otherwise several of the libctf functions will not properly find the data in
 677  680   * the container. If we're doing a dedup we also fix up the type mapping.
 678  681   */
 679  682  static int
 680  683  ctf_merge_common(ctf_merge_types_t *cmp)
 681  684  {
 682  685          int ret, i;
 683  686  
 684  687          ctf_phase_dump(cmp->cm_src, "merge-common-src", NULL);
 685  688          ctf_phase_dump(cmp->cm_out, "merge-common-dest", NULL);
 686  689  
 687  690          /* Pass 1 */
 688  691          for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
 689  692                  if (cmp->cm_tmap[i].cmt_forward == B_TRUE) {
 690  693                          ret = ctf_merge_add_sou(cmp, i, B_TRUE);
 691  694                          if (ret != 0) {
 692  695                                  return (ret);
 693  696                          }
 694  697                  }
 695  698          }
 696  699  
 697  700          /* Pass 2 */
 698  701          for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
 699  702                  if (cmp->cm_tmap[i].cmt_missing == B_TRUE) {
 700  703                          ret = ctf_merge_add_type(cmp, i);
 701  704                          if (ret != 0) {
 702  705                                  ctf_dprintf("Failed to merge type %d\n", i);
 703  706                                  return (ret);
 704  707                          }
 705  708                  }
 706  709          }
 707  710  
 708  711          ret = ctf_update(cmp->cm_out);
 709  712          if (ret != 0)
 710  713                  return (ret);
 711  714  
 712  715          if (cmp->cm_dedup == B_TRUE) {
 713  716                  ctf_merge_dedup_remap(cmp);
 714  717          }
 715  718  
 716  719          ctf_dprintf("Beginning merge pass 3\n");
 717  720          /* Pass 3 */
 718  721          for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
 719  722                  if (cmp->cm_tmap[i].cmt_fixup == B_TRUE) {
 720  723                          ret = ctf_merge_fixup_type(cmp, i);
 721  724                          if (ret != 0)
 722  725                                  return (ret);
 723  726                  }
 724  727          }
 725  728  
 726  729          return (0);
 727  730  }
 728  731  
 729  732  /*
 730  733   * Uniquification is slightly different from a stock merge. For starters, we
 731  734   * don't need to replace any forward references in the output. In this case
 732  735   * though, the types that already exist are in a parent container to the empty
 733  736   * output container.
 734  737   */
 735  738  static int
 736  739  ctf_merge_uniquify_types(ctf_merge_types_t *cmp)
 737  740  {
 738  741          int i, ret;
 739  742  
 740  743          for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
 741  744                  if (cmp->cm_tmap[i].cmt_missing == B_FALSE)
 742  745                          continue;
 743  746                  ret = ctf_merge_add_type(cmp, i);
 744  747                  if (ret != 0)
 745  748                          return (ret);
 746  749          }
 747  750  
 748  751          ret = ctf_update(cmp->cm_out);
 749  752          if (ret != 0)
 750  753                  return (ret);
 751  754  
 752  755          for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
 753  756                  if (cmp->cm_tmap[i].cmt_fixup == B_FALSE)
 754  757                          continue;
 755  758                  ret = ctf_merge_fixup_type(cmp, i);
 756  759                  if (ret != 0)
 757  760                          return (ret);
 758  761          }
 759  762  
 760  763          return (0);
 761  764  }
 762  765  
 763  766  static int
 764  767  ctf_merge_types_init(ctf_merge_types_t *cmp)
 765  768  {
 766  769          cmp->cm_tmap = ctf_alloc(sizeof (ctf_merge_tinfo_t) *
 767  770              (cmp->cm_src->ctf_typemax + 1));
 768  771          if (cmp->cm_tmap == NULL)
 769  772                  return (ctf_set_errno(cmp->cm_out, ENOMEM));
 770  773          bzero(cmp->cm_tmap, sizeof (ctf_merge_tinfo_t) *
 771  774              (cmp->cm_src->ctf_typemax + 1));
 772  775          return (0);
 773  776  }
 774  777  
 775  778  static void
 776  779  ctf_merge_types_fini(ctf_merge_types_t *cmp)
 777  780  {
 778  781          ctf_free(cmp->cm_tmap, sizeof (ctf_merge_tinfo_t) *
 779  782              (cmp->cm_src->ctf_typemax + 1));
 780  783  }
 781  784  
 782  785  /*
 783  786   * After performing a pass, we need to go through the object and function type
 784  787   * maps and potentially fix them up based on the new maps that we have.
 785  788   */
 786  789  static void
 787  790  ctf_merge_fixup_symmaps(ctf_merge_types_t *cmp, ctf_merge_input_t *cmi)
 788  791  {
 789  792          ctf_merge_objmap_t *cmo;
 790  793          ctf_merge_funcmap_t *cmf;
 791  794  
 792  795          for (cmo = list_head(&cmi->cmi_omap); cmo != NULL;
 793  796              cmo = list_next(&cmi->cmi_omap, cmo)) {
 794  797                  VERIFY3S(cmo->cmo_tid, !=, 0);
 795  798                  VERIFY(cmp->cm_tmap[cmo->cmo_tid].cmt_map != 0);
 796  799                  cmo->cmo_tid = cmp->cm_tmap[cmo->cmo_tid].cmt_map;
 797  800          }
 798  801  
 799  802          for (cmf = list_head(&cmi->cmi_fmap); cmf != NULL;
 800  803              cmf = list_next(&cmi->cmi_fmap, cmf)) {
 801  804                  int i;
 802  805  
 803  806                  VERIFY(cmp->cm_tmap[cmf->cmf_rtid].cmt_map != 0);
 804  807                  cmf->cmf_rtid = cmp->cm_tmap[cmf->cmf_rtid].cmt_map;
 805  808                  for (i = 0; i < cmf->cmf_argc; i++) {
 806  809                          VERIFY(cmp->cm_tmap[cmf->cmf_args[i]].cmt_map != 0);
 807  810                          cmf->cmf_args[i] =
 808  811                              cmp->cm_tmap[cmf->cmf_args[i]].cmt_map;
 809  812                  }
 810  813          }
 811  814  }
 812  815  
 813  816  /*
 814  817   * Merge the types contained inside of two input files. The second input file is
 815  818   * always going to be the destination. We're guaranteed that it's always
 816  819   * writeable.
 817  820   */
 818  821  static int
 819  822  ctf_merge_types(void *arg, void *arg2, void **outp, void *unsued)
 820  823  {
 821  824          int ret;
 822  825          ctf_merge_types_t cm;
 823  826          ctf_diff_t *cdp;
 824  827          ctf_merge_input_t *scmi = arg;
 825  828          ctf_merge_input_t *dcmi = arg2;
 826  829          ctf_file_t *out = dcmi->cmi_input;
 827  830          ctf_file_t *source = scmi->cmi_input;
 828  831  
 829  832          ctf_dprintf("merging %p->%p\n", source, out);
 830  833  
 831  834          if (!(out->ctf_flags & LCTF_RDWR))
 832  835                  return (ctf_set_errno(out, ECTF_RDONLY));
 833  836  
 834  837          if (ctf_getmodel(out) != ctf_getmodel(source))
 835  838                  return (ctf_set_errno(out, ECTF_DMODEL));
 836  839  
 837  840          if ((ret = ctf_diff_init(out, source, &cdp)) != 0)
 838  841                  return (ret);
 839  842  
 840  843          cm.cm_out = out;
 841  844          cm.cm_src = source;
 842  845          cm.cm_dedup = B_FALSE;
 843  846          cm.cm_unique = B_FALSE;
 844  847          ret = ctf_merge_types_init(&cm);
 845  848          if (ret != 0) {
 846  849                  ctf_diff_fini(cdp);
 847  850                  return (ctf_set_errno(out, ret));
 848  851          }
 849  852  
 850  853          ret = ctf_diff_types(cdp, ctf_merge_diffcb, &cm);
 851  854          if (ret != 0)
 852  855                  goto cleanup;
 853  856          ret = ctf_merge_common(&cm);
 854  857          ctf_dprintf("merge common returned with %d\n", ret);
 855  858          if (ret == 0) {
 856  859                  ret = ctf_update(out);
 857  860                  ctf_dprintf("update returned with %d\n", ret);
 858  861          } else {
 859  862                  goto cleanup;
 860  863          }
 861  864  
 862  865          /*
 863  866           * Now we need to fix up the object and function maps.
 864  867           */
 865  868          ctf_merge_fixup_symmaps(&cm, scmi);
 866  869  
 867  870          /*
 868  871           * Now that we've fixed things up, we need to give our function and
 869  872           * object maps to the destination, such that it can continue to update
 870  873           * them going forward.
 871  874           */
 872  875          list_move_tail(&dcmi->cmi_fmap, &scmi->cmi_fmap);
 873  876          list_move_tail(&dcmi->cmi_omap, &scmi->cmi_omap);
 874  877  
 875  878  cleanup:
 876  879          if (ret == 0)
 877  880                  *outp = dcmi;
 878  881          ctf_merge_types_fini(&cm);
 879  882          ctf_diff_fini(cdp);
 880  883          if (ret != 0)
 881  884                  return (ctf_errno(out));
 882  885          ctf_phase_bump();
 883  886          return (0);
 884  887  }
 885  888  
 886  889  static int
 887  890  ctf_uniquify_types(ctf_merge_t *cmh, ctf_file_t *src, ctf_file_t **outp)
 888  891  {
 889  892          int err, ret;
 890  893          ctf_file_t *out;
 891  894          ctf_merge_types_t cm;
 892  895          ctf_diff_t *cdp;
 893  896          ctf_merge_input_t *cmi;
 894  897          ctf_file_t *parent = cmh->cmh_unique;
 895  898  
 896  899          *outp = NULL;
 897  900          out = ctf_fdcreate(cmh->cmh_ofd, &err);
 898  901          if (out == NULL)
 899  902                  return (ctf_set_errno(src, err));
 900  903  
 901  904          out->ctf_parname = cmh->cmh_pname;
 902  905          if (ctf_setmodel(out, ctf_getmodel(parent)) != 0) {
 903  906                  (void) ctf_set_errno(src, ctf_errno(out));
 904  907                  ctf_close(out);
 905  908                  return (CTF_ERR);
 906  909          }
 907  910  
 908  911          if (ctf_import(out, parent) != 0) {
 909  912                  (void) ctf_set_errno(src, ctf_errno(out));
 910  913                  ctf_close(out);
 911  914                  return (CTF_ERR);
 912  915          }
 913  916  
 914  917          if ((ret = ctf_diff_init(parent, src, &cdp)) != 0) {
 915  918                  ctf_close(out);
 916  919                  return (ctf_set_errno(src, ctf_errno(parent)));
 917  920          }
 918  921  
 919  922          cm.cm_out = parent;
 920  923          cm.cm_src = src;
 921  924          cm.cm_dedup = B_FALSE;
 922  925          cm.cm_unique = B_TRUE;
 923  926          ret = ctf_merge_types_init(&cm);
 924  927          if (ret != 0) {
 925  928                  ctf_close(out);
 926  929                  ctf_diff_fini(cdp);
 927  930                  return (ctf_set_errno(src, ret));
 928  931          }
 929  932  
 930  933          ret = ctf_diff_types(cdp, ctf_merge_diffcb, &cm);
 931  934          if (ret == 0) {
 932  935                  cm.cm_out = out;
 933  936                  ret = ctf_merge_uniquify_types(&cm);
 934  937                  if (ret == 0)
 935  938                          ret = ctf_update(out);
 936  939          }
 937  940  
 938  941          if (ret != 0) {
 939  942                  ctf_merge_types_fini(&cm);
 940  943                  ctf_diff_fini(cdp);
 941  944                  return (ctf_set_errno(src, ctf_errno(cm.cm_out)));
 942  945          }
 943  946  
 944  947          for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL;
 945  948              cmi = list_next(&cmh->cmh_inputs, cmi)) {
 946  949                  ctf_merge_fixup_symmaps(&cm, cmi);
 947  950          }
 948  951  
 949  952          ctf_merge_types_fini(&cm);
 950  953          ctf_diff_fini(cdp);
 951  954          *outp = out;
 952  955          return (0);
 953  956  }
 954  957  
 955  958  static void
 956  959  ctf_merge_fini_input(ctf_merge_input_t *cmi)
 957  960  {
 958  961          ctf_merge_objmap_t *cmo;
 959  962          ctf_merge_funcmap_t *cmf;
 960  963  
 961  964          while ((cmo = list_remove_head(&cmi->cmi_omap)) != NULL)
 962  965                  ctf_free(cmo, sizeof (ctf_merge_objmap_t));
 963  966  
 964  967          while ((cmf = list_remove_head(&cmi->cmi_fmap)) != NULL)
 965  968                  ctf_free(cmf, sizeof (ctf_merge_funcmap_t) +
 966  969                      sizeof (ctf_id_t) * cmf->cmf_argc);
 967  970  
 968  971          if (cmi->cmi_created == B_TRUE && cmi->cmi_input != NULL)
 969  972                  ctf_close(cmi->cmi_input);
 970  973  
 971  974          ctf_free(cmi, sizeof (ctf_merge_input_t));
 972  975  }
 973  976  
 974  977  void
 975  978  ctf_merge_fini(ctf_merge_t *cmh)
 976  979  {
 977  980          size_t len;
 978  981          ctf_merge_input_t *cmi;
 979  982  
 980  983          if (cmh->cmh_label != NULL) {
 981  984                  len = strlen(cmh->cmh_label) + 1;
 982  985                  ctf_free(cmh->cmh_label, len);
 983  986          }
 984  987  
 985  988          if (cmh->cmh_pname != NULL) {
 986  989                  len = strlen(cmh->cmh_pname) + 1;
 987  990                  ctf_free(cmh->cmh_pname, len);
 988  991          }
 989  992  
 990  993          while ((cmi = list_remove_head(&cmh->cmh_inputs)) != NULL)
 991  994                  ctf_merge_fini_input(cmi);
 992  995  
 993  996          ctf_free(cmh, sizeof (ctf_merge_t));
 994  997  }
 995  998  
 996  999  ctf_merge_t *
 997 1000  ctf_merge_init(int fd, int *errp)
 998 1001  {
 999 1002          int err;
1000 1003          ctf_merge_t *out;
1001 1004          struct stat st;
1002 1005  
1003 1006          if (errp == NULL)
1004 1007                  errp = &err;
1005 1008  
1006 1009          if (fd != -1 && fstat(fd, &st) != 0) {
1007 1010                  *errp = EINVAL;
1008 1011                  return (NULL);
1009 1012          }
1010 1013  
1011 1014          out = ctf_alloc(sizeof (ctf_merge_t));
1012 1015          if (out == NULL) {
1013 1016                  *errp = ENOMEM;
1014 1017                  return (NULL);
1015 1018          }
1016 1019  
1017 1020          if (fd == -1) {
1018 1021                  out->cmh_msyms = B_FALSE;
1019 1022          } else {
1020 1023                  out->cmh_msyms = B_TRUE;
1021 1024          }
1022 1025  
1023 1026          list_create(&out->cmh_inputs, sizeof (ctf_merge_input_t),
1024 1027              offsetof(ctf_merge_input_t, cmi_node));
1025 1028          out->cmh_ninputs = 0;
1026 1029          out->cmh_nthreads = 1;
1027 1030          out->cmh_unique = NULL;
1028 1031          out->cmh_ofd = fd;
1029 1032          out->cmh_flags = 0;
1030 1033          out->cmh_label = NULL;
1031 1034          out->cmh_pname = NULL;
1032 1035  
1033 1036          return (out);
1034 1037  }
1035 1038  
1036 1039  int
1037 1040  ctf_merge_label(ctf_merge_t *cmh, const char *label)
1038 1041  {
1039 1042          char *dup;
1040 1043  
1041 1044          if (label == NULL)
1042 1045                  return (EINVAL);
1043 1046  
1044 1047          dup = ctf_strdup(label);
1045 1048          if (dup == NULL)
1046 1049                  return (EAGAIN);
1047 1050  
1048 1051          if (cmh->cmh_label != NULL) {
1049 1052                  size_t len = strlen(cmh->cmh_label) + 1;
1050 1053                  ctf_free(cmh->cmh_label, len);
1051 1054          }
1052 1055  
1053 1056          cmh->cmh_label = dup;
1054 1057          return (0);
1055 1058  }
1056 1059  
1057 1060  static int
1058 1061  ctf_merge_add_function(ctf_merge_input_t *cmi, ctf_funcinfo_t *fip, ulong_t idx,
1059 1062      const char *file, const char *name, const Elf64_Sym *symp)
1060 1063  {
1061 1064          ctf_merge_funcmap_t *fmap;
1062 1065  
1063 1066          fmap = ctf_alloc(sizeof (ctf_merge_funcmap_t) +
1064 1067              sizeof (ctf_id_t) * fip->ctc_argc);
1065 1068          if (fmap == NULL)
1066 1069                  return (ENOMEM);
1067 1070  
1068 1071          fmap->cmf_idx = idx;
1069 1072          fmap->cmf_sym = *symp;
1070 1073          fmap->cmf_rtid = fip->ctc_return;
1071 1074          fmap->cmf_flags = fip->ctc_flags;
1072 1075          fmap->cmf_argc = fip->ctc_argc;
1073 1076          fmap->cmf_name = name;
1074 1077          if (ELF64_ST_BIND(symp->st_info) == STB_LOCAL) {
1075 1078                  fmap->cmf_file = file;
1076 1079          } else {
1077 1080                  fmap->cmf_file = NULL;
1078 1081          }
1079 1082  
1080 1083          if (ctf_func_args(cmi->cmi_input, idx, fmap->cmf_argc,
1081 1084              fmap->cmf_args) != 0) {
1082 1085                  ctf_free(fmap, sizeof (ctf_merge_funcmap_t) +
1083 1086                      sizeof (ctf_id_t) * fip->ctc_argc);
1084 1087                  return (ctf_errno(cmi->cmi_input));
1085 1088          }
1086 1089  
1087 1090          ctf_dprintf("added initial function %s, %lu, %s %u\n", name, idx,
1088 1091              fmap->cmf_file != NULL ? fmap->cmf_file : "global",
1089 1092              ELF64_ST_BIND(symp->st_info));
1090 1093          list_insert_tail(&cmi->cmi_fmap, fmap);
1091 1094          return (0);
1092 1095  }
1093 1096  
1094 1097  static int
1095 1098  ctf_merge_add_object(ctf_merge_input_t *cmi, ctf_id_t id, ulong_t idx,
1096 1099      const char *file, const char *name, const Elf64_Sym *symp)
1097 1100  {
1098 1101          ctf_merge_objmap_t *cmo;
1099 1102  
1100 1103          cmo = ctf_alloc(sizeof (ctf_merge_objmap_t));
1101 1104          if (cmo == NULL)
1102 1105                  return (ENOMEM);
1103 1106  
1104 1107          cmo->cmo_name = name;
1105 1108          if (ELF64_ST_BIND(symp->st_info) == STB_LOCAL) {
1106 1109                  cmo->cmo_file = file;
1107 1110          } else {
1108 1111                  cmo->cmo_file = NULL;
1109 1112          }
1110 1113          cmo->cmo_idx = idx;
1111 1114          cmo->cmo_tid = id;
1112 1115          cmo->cmo_sym = *symp;
1113 1116          list_insert_tail(&cmi->cmi_omap, cmo);
1114 1117  
1115 1118          ctf_dprintf("added initial object %s, %lu, %ld, %s\n", name, idx, id,
1116 1119              cmo->cmo_file != NULL ? cmo->cmo_file : "global");
1117 1120  
1118 1121          return (0);
1119 1122  }
1120 1123  
1121 1124  static int
1122 1125  ctf_merge_add_symbol(const Elf64_Sym *symp, ulong_t idx, const char *file,
1123 1126      const char *name, boolean_t primary, void *arg)
1124 1127  {
1125 1128          ctf_merge_input_t *cmi = arg;
1126 1129          ctf_file_t *fp = cmi->cmi_input;
1127 1130          ushort_t *data, funcbase;
1128 1131          uint_t type;
1129 1132          ctf_funcinfo_t fi;
1130 1133  
1131 1134          /*
1132 1135           * See if there is type information for this. If there is no
1133 1136           * type information for this entry or no translation, then we
1134 1137           * will find the value zero. This indicates no type ID for
1135 1138           * objects and encodes unknown information for functions.
1136 1139           */
1137 1140          if (fp->ctf_sxlate[idx] == -1u)
1138 1141                  return (0);
1139 1142          data = (ushort_t *)((uintptr_t)fp->ctf_buf + fp->ctf_sxlate[idx]);
1140 1143          if (*data == 0)
1141 1144                  return (0);
1142 1145  
1143 1146          type = ELF64_ST_TYPE(symp->st_info);
1144 1147  
1145 1148          switch (type) {
1146 1149          case STT_FUNC:
1147 1150                  funcbase = *data;
1148 1151                  if (LCTF_INFO_KIND(fp, funcbase) != CTF_K_FUNCTION)
1149 1152                          return (0);
1150 1153                  data++;
1151 1154                  fi.ctc_return = *data;
1152 1155                  data++;
1153 1156                  fi.ctc_argc = LCTF_INFO_VLEN(fp, funcbase);
1154 1157                  fi.ctc_flags = 0;
1155 1158  
1156 1159                  if (fi.ctc_argc != 0 && data[fi.ctc_argc - 1] == 0) {
1157 1160                          fi.ctc_flags |= CTF_FUNC_VARARG;
1158 1161                          fi.ctc_argc--;
1159 1162                  }
1160 1163                  return (ctf_merge_add_function(cmi, &fi, idx, file, name,
1161 1164                      symp));
1162 1165          case STT_OBJECT:
1163 1166                  return (ctf_merge_add_object(cmi, *data, idx, file, name,
1164 1167                      symp));
1165 1168          default:
1166 1169                  return (0);
1167 1170          }
1168 1171  }
1169 1172  
1170 1173  /*
1171 1174   * Whenever we create an entry to merge, we then go and add a second empty
1172 1175   * ctf_file_t which we use for the purposes of our merging. It's not the best,
1173 1176   * but it's the best that we've got at the moment.
1174 1177   */
1175 1178  int
1176 1179  ctf_merge_add(ctf_merge_t *cmh, ctf_file_t *input)
1177 1180  {
1178 1181          int ret;
1179 1182          ctf_merge_input_t *cmi;
1180 1183          ctf_file_t *empty;
1181 1184  
1182 1185          ctf_dprintf("adding input %p\n", input);
1183 1186  
1184 1187          if (input->ctf_flags & LCTF_CHILD)
1185 1188                  return (ECTF_MCHILD);
1186 1189  
1187 1190          cmi = ctf_alloc(sizeof (ctf_merge_input_t));
1188 1191          if (cmi == NULL)
1189 1192                  return (ENOMEM);
1190 1193  
1191 1194          cmi->cmi_created = B_FALSE;
1192 1195          cmi->cmi_input = input;
1193 1196          list_create(&cmi->cmi_fmap, sizeof (ctf_merge_funcmap_t),
1194 1197              offsetof(ctf_merge_funcmap_t, cmf_node));
1195 1198          list_create(&cmi->cmi_omap, sizeof (ctf_merge_funcmap_t),
1196 1199              offsetof(ctf_merge_objmap_t, cmo_node));
1197 1200  
1198 1201          if (cmh->cmh_msyms == B_TRUE) {
1199 1202                  if ((ret = ctf_symtab_iter(input, ctf_merge_add_symbol,
1200 1203                      cmi)) != 0) {
1201 1204                          ctf_merge_fini_input(cmi);
1202 1205                          return (ret);
1203 1206                  }
1204 1207          }
1205 1208  
1206 1209          list_insert_tail(&cmh->cmh_inputs, cmi);
1207 1210          cmh->cmh_ninputs++;
1208 1211  
1209 1212          /* And now the empty one to merge into this */
1210 1213          cmi = ctf_alloc(sizeof (ctf_merge_input_t));
1211 1214          if (cmi == NULL)
1212 1215                  return (ENOMEM);
1213 1216          list_create(&cmi->cmi_fmap, sizeof (ctf_merge_funcmap_t),
1214 1217              offsetof(ctf_merge_funcmap_t, cmf_node));
1215 1218          list_create(&cmi->cmi_omap, sizeof (ctf_merge_funcmap_t),
1216 1219              offsetof(ctf_merge_objmap_t, cmo_node));
1217 1220  
1218 1221          empty = ctf_fdcreate(cmh->cmh_ofd, &ret);
1219 1222          if (empty == NULL)
1220 1223                  return (ret);
1221 1224          cmi->cmi_input = empty;
1222 1225          cmi->cmi_created = B_TRUE;
1223 1226  
1224 1227          if (ctf_setmodel(empty, ctf_getmodel(input)) == CTF_ERR) {
1225 1228                  return (ctf_errno(empty));
1226 1229          }
1227 1230  
1228 1231          list_insert_tail(&cmh->cmh_inputs, cmi);
1229 1232          cmh->cmh_ninputs++;
1230 1233          ctf_dprintf("added containers %p and %p\n", input, empty);
1231 1234          return (0);
1232 1235  }
1233 1236  
1234 1237  int
1235 1238  ctf_merge_uniquify(ctf_merge_t *cmh, ctf_file_t *u, const char *pname)
1236 1239  {
1237 1240          char *dup;
1238 1241  
1239 1242          if (u->ctf_flags & LCTF_CHILD)
1240 1243                  return (ECTF_MCHILD);
1241 1244          if (pname == NULL)
1242 1245                  return (EINVAL);
1243 1246          dup = ctf_strdup(pname);
1244 1247          if (dup == NULL)
1245 1248                  return (EINVAL);
1246 1249          if (cmh->cmh_pname != NULL) {
1247 1250                  size_t len = strlen(cmh->cmh_pname) + 1;
1248 1251                  ctf_free(cmh->cmh_pname, len);
1249 1252          }
1250 1253          cmh->cmh_pname = dup;
1251 1254          cmh->cmh_unique = u;
1252 1255          return (0);
1253 1256  }
1254 1257  
1255 1258  /*
1256 1259   * Symbol matching rules: the purpose of this is to verify that the type
1257 1260   * information that we have for a given symbol actually matches the output
1258 1261   * symbol. This is unfortunately complicated by several different factors:
1259 1262   *
1260 1263   * 1. When merging multiple .o's into a single item, the symbol table index will
1261 1264   * not match.
1262 1265   *
1263 1266   * 2. Visibility of a symbol may not be identical to the object file or the
1264 1267   * DWARF information due to symbol reduction via a mapfile.
1265 1268   *
1266 1269   * As such, we have to employ the following rules:
1267 1270   *
1268 1271   * 1. A global symbol table entry always matches a global CTF symbol with the
1269 1272   * same name.
1270 1273   *
1271 1274   * 2. A local symbol table entry always matches a local CTF symbol if they have
1272 1275   * the same name and they belong to the same file.
1273 1276   *
1274 1277   * 3. A weak symbol matches a non-weak symbol. This happens if we find that the
1275 1278   * types match, the values match, the sizes match, and the section indexes
1276 1279   * match. This happens when we do a conversion in one pass, it almost never
1277 1280   * happens when we're merging multiple object files. If we match a CTF global
1278 1281   * symbol, that's a fixed match, otherwise it's a fuzzy match.
1279 1282   *
1280 1283   * 4. A local symbol table entry matches a global CTF entry if the
1281 1284   * other pieces fail, but they have the same name. This is considered a fuzzy
1282 1285   * match and is not used unless we have no other options.
1283 1286   *
1284 1287   * 5. A weak symbol table entry matches a weak CTF entry if the other pieces
1285 1288   * fail, but they have the same name. This is considered a fuzzy match and is
1286 1289   * not used unless we have no other options. When merging independent .o files,
1287 1290   * this is often the only recourse we have to matching weak symbols.
1288 1291   *
1289 1292   * In the end, this would all be much simpler if we were able to do this as part
1290 1293   * of libld which would be able to do all the symbol transformations.
1291 1294   */
1292 1295  static boolean_t
1293 1296  ctf_merge_symbol_match(const char *ctf_file, const char *ctf_name,
1294 1297      const Elf64_Sym *ctf_symp, const char *symtab_file, const char *symtab_name,
1295 1298      const Elf64_Sym *symtab_symp, boolean_t *is_fuzzy)
1296 1299  {
1297 1300          *is_fuzzy = B_FALSE;
1298 1301          uint_t symtab_bind, ctf_bind;
1299 1302  
1300 1303          symtab_bind = ELF64_ST_BIND(symtab_symp->st_info);
1301 1304          ctf_bind = ELF64_ST_BIND(ctf_symp->st_info);
1302 1305  
1303 1306          ctf_dprintf("comparing merge match for %s/%s/%u->%s/%s/%u\n",
1304 1307              symtab_file, symtab_name, symtab_bind,
1305 1308              ctf_file, ctf_name, ctf_bind);
1306 1309          if (strcmp(ctf_name, symtab_name) != 0) {
1307 1310                  return (B_FALSE);
1308 1311          }
1309 1312  
1310 1313          if (symtab_bind == STB_GLOBAL && ctf_bind == STB_GLOBAL) {
1311 1314                  return (B_TRUE);
1312 1315          } else if (symtab_bind == STB_GLOBAL) {
1313 1316                  return (B_FALSE);
1314 1317          }
1315 1318  
1316 1319          if (ctf_bind == STB_LOCAL && ctf_bind == symtab_bind &&
1317 1320              ctf_file != NULL && symtab_file != NULL &&
1318 1321              strcmp(ctf_file, symtab_file) == 0) {
1319 1322                  return (B_TRUE);
1320 1323          }
1321 1324  
1322 1325          if (symtab_bind == STB_WEAK && ctf_bind != STB_WEAK &&
1323 1326              ELF64_ST_TYPE(symtab_symp->st_info) ==
1324 1327              ELF64_ST_TYPE(ctf_symp->st_info) &&
1325 1328              symtab_symp->st_value == ctf_symp->st_value &&
1326 1329              symtab_symp->st_size == ctf_symp->st_size &&
1327 1330              symtab_symp->st_shndx == ctf_symp->st_shndx) {
1328 1331                  if (ctf_bind == STB_GLOBAL) {
1329 1332                          return (B_TRUE);
1330 1333                  }
1331 1334  
1332 1335                  if (ctf_bind == STB_LOCAL && ctf_file != NULL &&
1333 1336                      symtab_file != NULL && strcmp(ctf_file, symtab_file) == 0) {
1334 1337                          *is_fuzzy = B_TRUE;
1335 1338                          return (B_TRUE);
1336 1339                  }
1337 1340          }
1338 1341  
1339 1342          if (ctf_bind == STB_GLOBAL ||
1340 1343              (ctf_bind == STB_WEAK && symtab_bind == STB_WEAK)) {
1341 1344                  *is_fuzzy = B_TRUE;
1342 1345                  return (B_TRUE);
1343 1346          }
1344 1347  
1345 1348          return (B_FALSE);
1346 1349  }
1347 1350  
1348 1351  /*
1349 1352   * For each symbol, try and find a match. We will attempt to find an exact
1350 1353   * match; however, we will settle for a fuzzy match in general. There is one
1351 1354   * case where we will not opt to use a fuzzy match, which is when performing the
1352 1355   * deduplication of a container. In such a case we are trying to reduce common
1353 1356   * types and a fuzzy match would be inappropriate as if we're in the context of
1354 1357   * a single container, the conversion process should have identified any exact
1355 1358   * or fuzzy matches that were required.
1356 1359   */
1357 1360  static int
1358 1361  ctf_merge_symbols(const Elf64_Sym *symp, ulong_t idx, const char *file,
1359 1362      const char *name, boolean_t primary, void *arg)
1360 1363  {
1361 1364          int err;
1362 1365          uint_t type, bind;
1363 1366          ctf_merge_symbol_arg_t *csa = arg;
1364 1367          ctf_file_t *fp = csa->cmsa_out;
1365 1368  
1366 1369          type = ELF64_ST_TYPE(symp->st_info);
1367 1370          bind = ELF64_ST_BIND(symp->st_info);
1368 1371  
1369 1372          ctf_dprintf("Trying to find match for %s/%s/%u\n", file, name,
1370 1373              ELF64_ST_BIND(symp->st_info));
1371 1374  
1372 1375          if (type == STT_OBJECT) {
1373 1376                  ctf_merge_objmap_t *cmo, *match = NULL;
1374 1377  
1375 1378                  for (cmo = list_head(csa->cmsa_objmap); cmo != NULL;
1376 1379                      cmo = list_next(csa->cmsa_objmap, cmo)) {
1377 1380                          boolean_t is_fuzzy = B_FALSE;
1378 1381                          if (ctf_merge_symbol_match(cmo->cmo_file, cmo->cmo_name,
1379 1382                              &cmo->cmo_sym, file, name, symp, &is_fuzzy)) {
1380 1383                                  if (is_fuzzy && csa->cmsa_dedup &&
1381 1384                                      bind != STB_WEAK) {
1382 1385                                          continue;
1383 1386                                  }
1384 1387                                  match = cmo;
1385 1388                                  if (is_fuzzy) {
1386 1389                                          continue;
1387 1390                                  }
1388 1391                                  break;
1389 1392                          }
1390 1393                  }
1391 1394  
1392 1395                  if (match == NULL) {
1393 1396                          return (0);
1394 1397                  }
1395 1398  
1396 1399                  if ((err = ctf_add_object(fp, idx, match->cmo_tid)) != 0) {
1397 1400                          ctf_dprintf("Failed to add symbol %s->%d: %s\n", name,
1398 1401                              match->cmo_tid, ctf_errmsg(ctf_errno(fp)));
1399 1402                          return (ctf_errno(fp));
1400 1403                  }
1401 1404                  ctf_dprintf("mapped object into output %s/%s->%ld\n", file,
1402 1405                      name, match->cmo_tid);
1403 1406          } else {
1404 1407                  ctf_merge_funcmap_t *cmf, *match = NULL;
1405 1408                  ctf_funcinfo_t fi;
1406 1409  
1407 1410                  for (cmf = list_head(csa->cmsa_funcmap); cmf != NULL;
1408 1411                      cmf = list_next(csa->cmsa_funcmap, cmf)) {
1409 1412                          boolean_t is_fuzzy = B_FALSE;
1410 1413                          if (ctf_merge_symbol_match(cmf->cmf_file, cmf->cmf_name,
1411 1414                              &cmf->cmf_sym, file, name, symp, &is_fuzzy)) {
1412 1415                                  if (is_fuzzy && csa->cmsa_dedup &&
1413 1416                                      bind != STB_WEAK) {
1414 1417                                          continue;
1415 1418                                  }
1416 1419                                  match = cmf;
1417 1420                                  if (is_fuzzy) {
1418 1421                                          continue;
1419 1422                                  }
1420 1423                                  break;
1421 1424                          }
1422 1425                  }
1423 1426  
1424 1427                  if (match == NULL) {
1425 1428                          return (0);
1426 1429                  }
1427 1430  
1428 1431                  fi.ctc_return = match->cmf_rtid;
1429 1432                  fi.ctc_argc = match->cmf_argc;
1430 1433                  fi.ctc_flags = match->cmf_flags;
1431 1434                  if ((err = ctf_add_function(fp, idx, &fi, match->cmf_args)) !=
1432 1435                      0) {
1433 1436                          ctf_dprintf("Failed to add function %s: %s\n", name,
1434 1437                              ctf_errmsg(ctf_errno(fp)));
1435 1438                          return (ctf_errno(fp));
1436 1439                  }
1437 1440                  ctf_dprintf("mapped function into output %s/%s\n", file,
1438 1441                      name);
1439 1442          }
1440 1443  
1441 1444          return (0);
1442 1445  }
1443 1446  
1444 1447  int
1445 1448  ctf_merge_merge(ctf_merge_t *cmh, ctf_file_t **outp)
1446 1449  {
1447 1450          int err, merr;
1448 1451          ctf_merge_input_t *cmi;
1449 1452          ctf_id_t ltype;
1450 1453          mergeq_t *mqp;
1451 1454          ctf_merge_input_t *final;
1452 1455          ctf_file_t *out;
1453 1456  
1454 1457          ctf_dprintf("Beginning ctf_merge_merge()\n");
1455 1458          if (cmh->cmh_label != NULL && cmh->cmh_unique != NULL) {
1456 1459                  const char *label = ctf_label_topmost(cmh->cmh_unique);
1457 1460                  if (label == NULL)
1458 1461                          return (ECTF_NOLABEL);
1459 1462                  if (strcmp(label, cmh->cmh_label) != 0)
1460 1463                          return (ECTF_LCONFLICT);
1461 1464          }
1462 1465  
1463 1466          if (mergeq_init(&mqp, cmh->cmh_nthreads) == -1) {
1464 1467                  return (errno);
1465 1468          }
1466 1469  
1467 1470          VERIFY(cmh->cmh_ninputs % 2 == 0);
1468 1471          for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL;
1469 1472              cmi = list_next(&cmh->cmh_inputs, cmi)) {
1470 1473                  if (mergeq_add(mqp, cmi) == -1) {
1471 1474                          err = errno;
1472 1475                          mergeq_fini(mqp);
1473 1476                  }
1474 1477          }
1475 1478  
1476 1479          err = mergeq_merge(mqp, ctf_merge_types, NULL, (void **)&final, &merr);
1477 1480          mergeq_fini(mqp);
1478 1481  
1479 1482          if (err == MERGEQ_ERROR) {
1480 1483                  return (errno);
1481 1484          } else if (err == MERGEQ_UERROR) {
1482 1485                  return (merr);
1483 1486          }
1484 1487  
1485 1488          /*
1486 1489           * Disassociate the generated ctf_file_t from the original input. That
1487 1490           * way when the input gets cleaned up, we don't accidentally kill the
1488 1491           * final reference to the ctf_file_t. If it gets uniquified then we'll
1489 1492           * kill it.
1490 1493           */
1491 1494          VERIFY(final->cmi_input != NULL);
1492 1495          out = final->cmi_input;
1493 1496          final->cmi_input = NULL;
1494 1497  
1495 1498          ctf_dprintf("preparing to uniquify against: %p\n", cmh->cmh_unique);
1496 1499          if (cmh->cmh_unique != NULL) {
1497 1500                  ctf_file_t *u;
1498 1501                  err = ctf_uniquify_types(cmh, out, &u);
1499 1502                  if (err != 0) {
1500 1503                          err = ctf_errno(out);
1501 1504                          ctf_close(out);
1502 1505                          return (err);
1503 1506                  }
1504 1507                  ctf_close(out);
1505 1508                  out = u;
1506 1509          }
1507 1510  
1508 1511          ltype = out->ctf_typemax;
1509 1512          if ((out->ctf_flags & LCTF_CHILD) && ltype != 0)
1510 1513                  ltype += CTF_CHILD_START;
1511 1514          ctf_dprintf("trying to add the label\n");
1512 1515          if (cmh->cmh_label != NULL &&
1513 1516              ctf_add_label(out, cmh->cmh_label, ltype, 0) != 0) {
1514 1517                  ctf_close(out);
1515 1518                  return (ctf_errno(out));
1516 1519          }
1517 1520  
1518 1521          ctf_dprintf("merging symbols and the like\n");
1519 1522          if (cmh->cmh_msyms == B_TRUE) {
1520 1523                  ctf_merge_symbol_arg_t arg;
1521 1524                  arg.cmsa_objmap = &final->cmi_omap;
1522 1525                  arg.cmsa_funcmap = &final->cmi_fmap;
1523 1526                  arg.cmsa_out = out;
1524 1527                  arg.cmsa_dedup = B_FALSE;
1525 1528                  err = ctf_symtab_iter(out, ctf_merge_symbols, &arg);
1526 1529                  if (err != 0) {
1527 1530                          ctf_close(out);
1528 1531                          return (err);
1529 1532                  }
1530 1533          }
1531 1534  
1532 1535          err = ctf_update(out);
1533 1536          if (err != 0) {
1534 1537                  err = ctf_errno(out);
1535 1538                  ctf_close(out);
1536 1539                  return (err);
1537 1540          }
1538 1541  
1539 1542          *outp = out;
1540 1543          return (0);
1541 1544  }
1542 1545  
1543 1546  /*
1544 1547   * When we get told that something is unique, eg. same is B_FALSE, then that
1545 1548   * tells us that we need to add it to the output. If same is B_TRUE, then we'll
1546 1549   * want to record it in the mapping table so that we know how to redirect types
1547 1550   * to the extant ones.
1548 1551   */
1549 1552  static void
1550 1553  ctf_dedup_cb(ctf_file_t *ifp, ctf_id_t iid, boolean_t same, ctf_file_t *ofp,
1551 1554      ctf_id_t oid, void *arg)
1552 1555  {
1553 1556          ctf_merge_types_t *cmp = arg;
1554 1557          ctf_merge_tinfo_t *cmt = cmp->cm_tmap;
1555 1558  
1556 1559          if (same == B_TRUE) {
1557 1560                  /*
1558 1561                   * The output id here may itself map to something else.
1559 1562                   * Therefore, we need to basically walk a chain and see what it
1560 1563                   * points to until it itself points to a base type, eg. -1.
1561 1564                   * Otherwise we'll dedup to something which no longer exists.
1562 1565                   */
1563 1566                  while (cmt[oid].cmt_missing == B_FALSE)
1564 1567                          oid = cmt[oid].cmt_map;
1565 1568                  cmt[iid].cmt_map = oid;
1566 1569                  ctf_dprintf("%d->%d \n", iid, oid);
1567 1570          } else {
1568 1571                  VERIFY(cmt[iid].cmt_map == 0);
1569 1572                  cmt[iid].cmt_missing = B_TRUE;
1570 1573                  ctf_dprintf("%d is missing\n", iid);
1571 1574          }
1572 1575  }
1573 1576  
1574 1577  /*
1575 1578   * Dedup a CTF container.
1576 1579   *
1577 1580   * DWARF and other encoding formats that we use to create CTF data may create
1578 1581   * multiple copies of a given type. However, after doing a conversion, and
1579 1582   * before doing a merge, we'd prefer, if possible, to have every input container
1580 1583   * to be unique.
1581 1584   *
1582 1585   * Doing a deduplication is like a normal merge. However, when we diff the types
1583 1586   * in the container, rather than doing a normal diff, we instead want to diff
1584 1587   * against any already processed types. eg, for a given type i in a container,
1585 1588   * we want to diff it from 0 to i - 1.
1586 1589   */
1587 1590  int
1588 1591  ctf_merge_dedup(ctf_merge_t *cmp, ctf_file_t **outp)
1589 1592  {
1590 1593          int ret;
1591 1594          ctf_diff_t *cdp = NULL;
1592 1595          ctf_merge_input_t *cmi, *cmc;
1593 1596          ctf_file_t *ifp, *ofp;
1594 1597          ctf_merge_types_t cm;
1595 1598  
1596 1599          if (cmp == NULL || outp == NULL)
1597 1600                  return (EINVAL);
1598 1601  
1599 1602          ctf_dprintf("encountered %d inputs\n", cmp->cmh_ninputs);
1600 1603          if (cmp->cmh_ninputs != 2)
1601 1604                  return (EINVAL);
1602 1605  
1603 1606          ctf_dprintf("passed argument sanity check\n");
1604 1607  
1605 1608          cmi = list_head(&cmp->cmh_inputs);
1606 1609          VERIFY(cmi != NULL);
1607 1610          cmc = list_next(&cmp->cmh_inputs, cmi);
1608 1611          VERIFY(cmc != NULL);
1609 1612          ifp = cmi->cmi_input;
1610 1613          ofp = cmc->cmi_input;
1611 1614          VERIFY(ifp != NULL);
1612 1615          VERIFY(ofp != NULL);
1613 1616          cm.cm_src = ifp;
1614 1617          cm.cm_out = ofp;
1615 1618          cm.cm_dedup = B_TRUE;
1616 1619          cm.cm_unique = B_FALSE;
1617 1620  
1618 1621          if ((ret = ctf_merge_types_init(&cm)) != 0) {
1619 1622                  return (ret);
1620 1623          }
1621 1624  
1622 1625          if ((ret = ctf_diff_init(ifp, ifp, &cdp)) != 0)
1623 1626                  goto err;
1624 1627  
1625 1628          ctf_dprintf("Successfully initialized dedup\n");
1626 1629          if ((ret = ctf_diff_self(cdp, ctf_dedup_cb, &cm)) != 0)
1627 1630                  goto err;
1628 1631  
1629 1632          ctf_dprintf("Successfully diffed types\n");
1630 1633          ret = ctf_merge_common(&cm);
1631 1634          ctf_dprintf("deduping types result: %d\n", ret);
1632 1635          if (ret == 0)
1633 1636                  ret = ctf_update(cm.cm_out);
1634 1637          if (ret != 0)
1635 1638                  goto err;
1636 1639  
1637 1640          ctf_dprintf("Successfully deduped types\n");
1638 1641          ctf_phase_dump(cm.cm_out, "dedup-pre-syms", NULL);
1639 1642  
1640 1643          /*
1641 1644           * Now we need to fix up the object and function maps.
1642 1645           */
1643 1646          ctf_merge_fixup_symmaps(&cm, cmi);
1644 1647  
1645 1648          if (cmp->cmh_msyms == B_TRUE) {
1646 1649                  ctf_merge_symbol_arg_t arg;
1647 1650                  arg.cmsa_objmap = &cmi->cmi_omap;
1648 1651                  arg.cmsa_funcmap = &cmi->cmi_fmap;
1649 1652                  arg.cmsa_out = cm.cm_out;
1650 1653                  arg.cmsa_dedup = B_TRUE;
1651 1654                  ret = ctf_symtab_iter(cm.cm_out, ctf_merge_symbols, &arg);
1652 1655                  if (ret != 0) {
1653 1656                          ctf_dprintf("failed to dedup symbols: %s\n",
1654 1657                              ctf_errmsg(ret));
1655 1658                          goto err;
1656 1659                  }
1657 1660          }
1658 1661  
1659 1662          ret = ctf_update(cm.cm_out);
1660 1663          if (ret == 0) {
1661 1664                  cmc->cmi_input = NULL;
1662 1665                  *outp = cm.cm_out;
1663 1666          }
1664 1667          ctf_phase_dump(cm.cm_out, "dedup-post-syms", NULL);
1665 1668  err:
1666 1669          ctf_merge_types_fini(&cm);
1667 1670          ctf_diff_fini(cdp);
1668 1671          return (ret);
1669 1672  }
1670 1673  
1671 1674  int
1672 1675  ctf_merge_set_nthreads(ctf_merge_t *cmp, const uint_t nthrs)
1673 1676  {
1674 1677          if (nthrs == 0)
1675 1678                  return (EINVAL);
1676 1679          cmp->cmh_nthreads = nthrs;
1677 1680          return (0);
1678 1681  }
  
    | 
      ↓ open down ↓ | 
    1317 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX