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