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