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. All rights reserved. 14*7fd79137SRobert Mustacchi */ 15*7fd79137SRobert Mustacchi 16*7fd79137SRobert Mustacchi /* 17*7fd79137SRobert Mustacchi * The following is a basic overview of how we diff types in containers (the 18*7fd79137SRobert Mustacchi * generally interesting part of diff, and what's used by merge). We maintain 19*7fd79137SRobert Mustacchi * two mapping tables, a table of forward mappings (src->dest), and a reverse 20*7fd79137SRobert Mustacchi * mapping (dest->src). Both are initialized to contain no mapping, and can also 21*7fd79137SRobert Mustacchi * be updated to contain a negative mapping. 22*7fd79137SRobert Mustacchi * 23*7fd79137SRobert Mustacchi * What we do first is iterate over each type in the src container, and compare 24*7fd79137SRobert Mustacchi * it with a type in the destination container. This may involve doing recursive 25*7fd79137SRobert Mustacchi * comparisons -- which can involve cycles. To deal with this, whenever we 26*7fd79137SRobert Mustacchi * encounter something which may be cyclic, we insert a guess. In other words, 27*7fd79137SRobert Mustacchi * we assume that it may be true. This is necessary for the classic case of the 28*7fd79137SRobert Mustacchi * following structure: 29*7fd79137SRobert Mustacchi * 30*7fd79137SRobert Mustacchi * struct foo { 31*7fd79137SRobert Mustacchi * struct foo *foo_next; 32*7fd79137SRobert Mustacchi * }; 33*7fd79137SRobert Mustacchi * 34*7fd79137SRobert Mustacchi * If it turns out that we were wrong, we discard our guesses. 35*7fd79137SRobert Mustacchi * 36*7fd79137SRobert Mustacchi * If we find that a given type in src has no corresponding entry in dst, we 37*7fd79137SRobert Mustacchi * then mark its map as CTF_ERR (-1) to indicate that it has *no* match, as 38*7fd79137SRobert Mustacchi * opposed to the default value of 0, which indicates an unknown match. 39*7fd79137SRobert Mustacchi * Once we've done the first iteration through src, we know at that point in 40*7fd79137SRobert Mustacchi * time whether everything in dst is similar or not and can simply walk over it 41*7fd79137SRobert Mustacchi * and don't have to do any additional checks. 42*7fd79137SRobert Mustacchi */ 43*7fd79137SRobert Mustacchi 44*7fd79137SRobert Mustacchi #include <libctf.h> 45*7fd79137SRobert Mustacchi #include <ctf_impl.h> 46*7fd79137SRobert Mustacchi #include <sys/debug.h> 47*7fd79137SRobert Mustacchi 48*7fd79137SRobert Mustacchi typedef struct ctf_diff_func { 49*7fd79137SRobert Mustacchi const char *cdf_name; 50*7fd79137SRobert Mustacchi ulong_t cdf_symidx; 51*7fd79137SRobert Mustacchi ulong_t cdf_matchidx; 52*7fd79137SRobert Mustacchi } ctf_diff_func_t; 53*7fd79137SRobert Mustacchi 54*7fd79137SRobert Mustacchi typedef struct ctf_diff_obj { 55*7fd79137SRobert Mustacchi const char *cdo_name; 56*7fd79137SRobert Mustacchi ulong_t cdo_symidx; 57*7fd79137SRobert Mustacchi ctf_id_t cdo_id; 58*7fd79137SRobert Mustacchi ulong_t cdo_matchidx; 59*7fd79137SRobert Mustacchi } ctf_diff_obj_t; 60*7fd79137SRobert Mustacchi 61*7fd79137SRobert Mustacchi typedef struct ctf_diff_guess { 62*7fd79137SRobert Mustacchi struct ctf_diff_guess *cdg_next; 63*7fd79137SRobert Mustacchi ctf_id_t cdg_iid; 64*7fd79137SRobert Mustacchi ctf_id_t cdg_oid; 65*7fd79137SRobert Mustacchi } ctf_diff_guess_t; 66*7fd79137SRobert Mustacchi 67*7fd79137SRobert Mustacchi /* typedef in libctf.h */ 68*7fd79137SRobert Mustacchi struct ctf_diff { 69*7fd79137SRobert Mustacchi uint_t cds_flags; 70*7fd79137SRobert Mustacchi boolean_t cds_tvalid; /* types valid */ 71*7fd79137SRobert Mustacchi ctf_file_t *cds_ifp; 72*7fd79137SRobert Mustacchi ctf_file_t *cds_ofp; 73*7fd79137SRobert Mustacchi ctf_id_t *cds_forward; 74*7fd79137SRobert Mustacchi ctf_id_t *cds_reverse; 75*7fd79137SRobert Mustacchi size_t cds_fsize; 76*7fd79137SRobert Mustacchi size_t cds_rsize; 77*7fd79137SRobert Mustacchi ctf_diff_type_f cds_func; 78*7fd79137SRobert Mustacchi ctf_diff_guess_t *cds_guess; 79*7fd79137SRobert Mustacchi void *cds_arg; 80*7fd79137SRobert Mustacchi uint_t cds_nifuncs; 81*7fd79137SRobert Mustacchi uint_t cds_nofuncs; 82*7fd79137SRobert Mustacchi uint_t cds_nextifunc; 83*7fd79137SRobert Mustacchi uint_t cds_nextofunc; 84*7fd79137SRobert Mustacchi ctf_diff_func_t *cds_ifuncs; 85*7fd79137SRobert Mustacchi ctf_diff_func_t *cds_ofuncs; 86*7fd79137SRobert Mustacchi boolean_t cds_ffillip; 87*7fd79137SRobert Mustacchi boolean_t cds_fvalid; 88*7fd79137SRobert Mustacchi uint_t cds_niobj; 89*7fd79137SRobert Mustacchi uint_t cds_noobj; 90*7fd79137SRobert Mustacchi uint_t cds_nextiobj; 91*7fd79137SRobert Mustacchi uint_t cds_nextoobj; 92*7fd79137SRobert Mustacchi ctf_diff_obj_t *cds_iobj; 93*7fd79137SRobert Mustacchi ctf_diff_obj_t *cds_oobj; 94*7fd79137SRobert Mustacchi boolean_t cds_ofillip; 95*7fd79137SRobert Mustacchi boolean_t cds_ovalid; 96*7fd79137SRobert Mustacchi }; 97*7fd79137SRobert Mustacchi 98*7fd79137SRobert Mustacchi #define TINDEX(tid) (tid - 1) 99*7fd79137SRobert Mustacchi 100*7fd79137SRobert Mustacchi /* 101*7fd79137SRobert Mustacchi * Team Diff 102*7fd79137SRobert Mustacchi */ 103*7fd79137SRobert Mustacchi static int ctf_diff_type(ctf_diff_t *, ctf_file_t *, ctf_id_t, ctf_file_t *, 104*7fd79137SRobert Mustacchi ctf_id_t); 105*7fd79137SRobert Mustacchi 106*7fd79137SRobert Mustacchi static int 107*7fd79137SRobert Mustacchi ctf_diff_name(ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp, ctf_id_t oid) 108*7fd79137SRobert Mustacchi { 109*7fd79137SRobert Mustacchi const char *iname, *oname; 110*7fd79137SRobert Mustacchi const ctf_type_t *itp, *otp; 111*7fd79137SRobert Mustacchi 112*7fd79137SRobert Mustacchi if ((itp = ctf_lookup_by_id(&ifp, iid)) == NULL) 113*7fd79137SRobert Mustacchi return (CTF_ERR); 114*7fd79137SRobert Mustacchi 115*7fd79137SRobert Mustacchi if ((otp = ctf_lookup_by_id(&ofp, oid)) == NULL) 116*7fd79137SRobert Mustacchi return (ctf_set_errno(ifp, iid)); 117*7fd79137SRobert Mustacchi 118*7fd79137SRobert Mustacchi iname = ctf_strptr(ifp, itp->ctt_name); 119*7fd79137SRobert Mustacchi oname = ctf_strptr(ofp, otp->ctt_name); 120*7fd79137SRobert Mustacchi 121*7fd79137SRobert Mustacchi if ((iname == NULL || oname == NULL) && (iname != oname)) 122*7fd79137SRobert Mustacchi return (B_TRUE); 123*7fd79137SRobert Mustacchi 124*7fd79137SRobert Mustacchi /* Two anonymous names are the same */ 125*7fd79137SRobert Mustacchi if (iname == NULL && oname == NULL) 126*7fd79137SRobert Mustacchi return (B_FALSE); 127*7fd79137SRobert Mustacchi 128*7fd79137SRobert Mustacchi return (strcmp(iname, oname) == 0 ? B_FALSE: B_TRUE); 129*7fd79137SRobert Mustacchi } 130*7fd79137SRobert Mustacchi 131*7fd79137SRobert Mustacchi /* 132*7fd79137SRobert Mustacchi * For floats and ints 133*7fd79137SRobert Mustacchi */ 134*7fd79137SRobert Mustacchi static int 135*7fd79137SRobert Mustacchi ctf_diff_number(ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp, ctf_id_t oid) 136*7fd79137SRobert Mustacchi { 137*7fd79137SRobert Mustacchi ctf_encoding_t ien, den; 138*7fd79137SRobert Mustacchi 139*7fd79137SRobert Mustacchi if (ctf_type_encoding(ifp, iid, &ien) != 0) 140*7fd79137SRobert Mustacchi return (CTF_ERR); 141*7fd79137SRobert Mustacchi 142*7fd79137SRobert Mustacchi if (ctf_type_encoding(ofp, oid, &den) != 0) 143*7fd79137SRobert Mustacchi return (ctf_set_errno(ifp, iid)); 144*7fd79137SRobert Mustacchi 145*7fd79137SRobert Mustacchi if (bcmp(&ien, &den, sizeof (ctf_encoding_t)) != 0) 146*7fd79137SRobert Mustacchi return (B_TRUE); 147*7fd79137SRobert Mustacchi 148*7fd79137SRobert Mustacchi return (B_FALSE); 149*7fd79137SRobert Mustacchi } 150*7fd79137SRobert Mustacchi 151*7fd79137SRobert Mustacchi /* 152*7fd79137SRobert Mustacchi * Two typedefs are equivalent, if after we resolve a chain of typedefs, they 153*7fd79137SRobert Mustacchi * point to equivalent types. This means that if a size_t is defined as follows: 154*7fd79137SRobert Mustacchi * 155*7fd79137SRobert Mustacchi * size_t -> ulong_t -> unsigned long 156*7fd79137SRobert Mustacchi * size_t -> unsigned long 157*7fd79137SRobert Mustacchi * 158*7fd79137SRobert Mustacchi * That we'll ultimately end up treating them the same. 159*7fd79137SRobert Mustacchi */ 160*7fd79137SRobert Mustacchi static int 161*7fd79137SRobert Mustacchi ctf_diff_typedef(ctf_diff_t *cds, ctf_file_t *ifp, ctf_id_t iid, 162*7fd79137SRobert Mustacchi ctf_file_t *ofp, ctf_id_t oid) 163*7fd79137SRobert Mustacchi { 164*7fd79137SRobert Mustacchi ctf_id_t iref = CTF_ERR, oref = CTF_ERR; 165*7fd79137SRobert Mustacchi 166*7fd79137SRobert Mustacchi while (ctf_type_kind(ifp, iid) == CTF_K_TYPEDEF) { 167*7fd79137SRobert Mustacchi iref = ctf_type_reference(ifp, iid); 168*7fd79137SRobert Mustacchi if (iref == CTF_ERR) 169*7fd79137SRobert Mustacchi return (CTF_ERR); 170*7fd79137SRobert Mustacchi iid = iref; 171*7fd79137SRobert Mustacchi } 172*7fd79137SRobert Mustacchi 173*7fd79137SRobert Mustacchi while (ctf_type_kind(ofp, oid) == CTF_K_TYPEDEF) { 174*7fd79137SRobert Mustacchi oref = ctf_type_reference(ofp, oid); 175*7fd79137SRobert Mustacchi if (oref == CTF_ERR) 176*7fd79137SRobert Mustacchi return (CTF_ERR); 177*7fd79137SRobert Mustacchi oid = oref; 178*7fd79137SRobert Mustacchi } 179*7fd79137SRobert Mustacchi 180*7fd79137SRobert Mustacchi VERIFY(iref != CTF_ERR && oref != CTF_ERR); 181*7fd79137SRobert Mustacchi return (ctf_diff_type(cds, ifp, iref, ofp, oref)); 182*7fd79137SRobert Mustacchi } 183*7fd79137SRobert Mustacchi 184*7fd79137SRobert Mustacchi /* 185*7fd79137SRobert Mustacchi * Two qualifiers are equivalent iff they point to two equivalent types. 186*7fd79137SRobert Mustacchi */ 187*7fd79137SRobert Mustacchi static int 188*7fd79137SRobert Mustacchi ctf_diff_qualifier(ctf_diff_t *cds, ctf_file_t *ifp, ctf_id_t iid, 189*7fd79137SRobert Mustacchi ctf_file_t *ofp, ctf_id_t oid) 190*7fd79137SRobert Mustacchi { 191*7fd79137SRobert Mustacchi ctf_id_t iref, oref; 192*7fd79137SRobert Mustacchi 193*7fd79137SRobert Mustacchi iref = ctf_type_reference(ifp, iid); 194*7fd79137SRobert Mustacchi if (iref == CTF_ERR) 195*7fd79137SRobert Mustacchi return (CTF_ERR); 196*7fd79137SRobert Mustacchi 197*7fd79137SRobert Mustacchi oref = ctf_type_reference(ofp, oid); 198*7fd79137SRobert Mustacchi if (oref == CTF_ERR) 199*7fd79137SRobert Mustacchi return (ctf_set_errno(ifp, ctf_errno(ofp))); 200*7fd79137SRobert Mustacchi 201*7fd79137SRobert Mustacchi return (ctf_diff_type(cds, ifp, iref, ofp, oref)); 202*7fd79137SRobert Mustacchi } 203*7fd79137SRobert Mustacchi 204*7fd79137SRobert Mustacchi /* 205*7fd79137SRobert Mustacchi * Two arrays are the same iff they have the same type for contents, the same 206*7fd79137SRobert Mustacchi * type for the index, and the same number of elements. 207*7fd79137SRobert Mustacchi */ 208*7fd79137SRobert Mustacchi static int 209*7fd79137SRobert Mustacchi ctf_diff_array(ctf_diff_t *cds, ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp, 210*7fd79137SRobert Mustacchi ctf_id_t oid) 211*7fd79137SRobert Mustacchi { 212*7fd79137SRobert Mustacchi int ret; 213*7fd79137SRobert Mustacchi ctf_arinfo_t iar, oar; 214*7fd79137SRobert Mustacchi 215*7fd79137SRobert Mustacchi if (ctf_array_info(ifp, iid, &iar) == CTF_ERR) 216*7fd79137SRobert Mustacchi return (CTF_ERR); 217*7fd79137SRobert Mustacchi 218*7fd79137SRobert Mustacchi if (ctf_array_info(ofp, oid, &oar) == CTF_ERR) 219*7fd79137SRobert Mustacchi return (ctf_set_errno(ifp, ctf_errno(ofp))); 220*7fd79137SRobert Mustacchi 221*7fd79137SRobert Mustacchi ret = ctf_diff_type(cds, ifp, iar.ctr_contents, ofp, oar.ctr_contents); 222*7fd79137SRobert Mustacchi if (ret != B_FALSE) 223*7fd79137SRobert Mustacchi return (ret); 224*7fd79137SRobert Mustacchi 225*7fd79137SRobert Mustacchi if (iar.ctr_nelems != oar.ctr_nelems) 226*7fd79137SRobert Mustacchi return (B_TRUE); 227*7fd79137SRobert Mustacchi 228*7fd79137SRobert Mustacchi /* 229*7fd79137SRobert Mustacchi * If we're ignoring integer types names, then we're trying to do a bit 230*7fd79137SRobert Mustacchi * of a logical diff and we don't really care about the fact that the 231*7fd79137SRobert Mustacchi * index element might not be the same here, what we care about are the 232*7fd79137SRobert Mustacchi * number of elements and that they're the same type. 233*7fd79137SRobert Mustacchi */ 234*7fd79137SRobert Mustacchi if ((cds->cds_flags & CTF_DIFF_F_IGNORE_INTNAMES) == 0) { 235*7fd79137SRobert Mustacchi ret = ctf_diff_type(cds, ifp, iar.ctr_index, ofp, 236*7fd79137SRobert Mustacchi oar.ctr_index); 237*7fd79137SRobert Mustacchi if (ret != B_FALSE) 238*7fd79137SRobert Mustacchi return (ret); 239*7fd79137SRobert Mustacchi } 240*7fd79137SRobert Mustacchi 241*7fd79137SRobert Mustacchi return (B_FALSE); 242*7fd79137SRobert Mustacchi } 243*7fd79137SRobert Mustacchi 244*7fd79137SRobert Mustacchi /* 245*7fd79137SRobert Mustacchi * Two function pointers are the same if the following is all true: 246*7fd79137SRobert Mustacchi * 247*7fd79137SRobert Mustacchi * o They have the same return type 248*7fd79137SRobert Mustacchi * o They have the same number of arguments 249*7fd79137SRobert Mustacchi * o The arguments are of the same type 250*7fd79137SRobert Mustacchi * o They have the same flags 251*7fd79137SRobert Mustacchi */ 252*7fd79137SRobert Mustacchi static int 253*7fd79137SRobert Mustacchi ctf_diff_fptr(ctf_diff_t *cds, ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp, 254*7fd79137SRobert Mustacchi ctf_id_t oid) 255*7fd79137SRobert Mustacchi { 256*7fd79137SRobert Mustacchi int ret, i; 257*7fd79137SRobert Mustacchi ctf_funcinfo_t ifunc, ofunc; 258*7fd79137SRobert Mustacchi ctf_id_t *iids, *oids; 259*7fd79137SRobert Mustacchi 260*7fd79137SRobert Mustacchi if (ctf_func_info_by_id(ifp, iid, &ifunc) == CTF_ERR) 261*7fd79137SRobert Mustacchi return (CTF_ERR); 262*7fd79137SRobert Mustacchi 263*7fd79137SRobert Mustacchi if (ctf_func_info_by_id(ofp, oid, &ofunc) == CTF_ERR) 264*7fd79137SRobert Mustacchi return (ctf_set_errno(ifp, ctf_errno(ofp))); 265*7fd79137SRobert Mustacchi 266*7fd79137SRobert Mustacchi if (ifunc.ctc_argc != ofunc.ctc_argc) 267*7fd79137SRobert Mustacchi return (B_TRUE); 268*7fd79137SRobert Mustacchi 269*7fd79137SRobert Mustacchi if (ifunc.ctc_flags != ofunc.ctc_flags) 270*7fd79137SRobert Mustacchi return (B_TRUE); 271*7fd79137SRobert Mustacchi 272*7fd79137SRobert Mustacchi ret = ctf_diff_type(cds, ifp, ifunc.ctc_return, ofp, ofunc.ctc_return); 273*7fd79137SRobert Mustacchi if (ret != B_FALSE) 274*7fd79137SRobert Mustacchi return (ret); 275*7fd79137SRobert Mustacchi 276*7fd79137SRobert Mustacchi iids = ctf_alloc(sizeof (ctf_id_t) * ifunc.ctc_argc); 277*7fd79137SRobert Mustacchi if (iids == NULL) 278*7fd79137SRobert Mustacchi return (ctf_set_errno(ifp, ENOMEM)); 279*7fd79137SRobert Mustacchi 280*7fd79137SRobert Mustacchi oids = ctf_alloc(sizeof (ctf_id_t) * ifunc.ctc_argc); 281*7fd79137SRobert Mustacchi if (oids == NULL) { 282*7fd79137SRobert Mustacchi ctf_free(iids, sizeof (ctf_id_t) * ifunc.ctc_argc); 283*7fd79137SRobert Mustacchi return (ctf_set_errno(ifp, ENOMEM)); 284*7fd79137SRobert Mustacchi } 285*7fd79137SRobert Mustacchi 286*7fd79137SRobert Mustacchi if (ctf_func_args_by_id(ifp, iid, ifunc.ctc_argc, iids) == CTF_ERR) { 287*7fd79137SRobert Mustacchi ret = CTF_ERR; 288*7fd79137SRobert Mustacchi goto out; 289*7fd79137SRobert Mustacchi } 290*7fd79137SRobert Mustacchi 291*7fd79137SRobert Mustacchi if (ctf_func_args_by_id(ofp, oid, ofunc.ctc_argc, oids) == CTF_ERR) { 292*7fd79137SRobert Mustacchi ret = ctf_set_errno(ifp, ctf_errno(ofp)); 293*7fd79137SRobert Mustacchi goto out; 294*7fd79137SRobert Mustacchi } 295*7fd79137SRobert Mustacchi 296*7fd79137SRobert Mustacchi ret = B_TRUE; 297*7fd79137SRobert Mustacchi for (i = 0; i < ifunc.ctc_argc; i++) { 298*7fd79137SRobert Mustacchi ret = ctf_diff_type(cds, ifp, iids[i], ofp, oids[i]); 299*7fd79137SRobert Mustacchi if (ret != B_FALSE) 300*7fd79137SRobert Mustacchi goto out; 301*7fd79137SRobert Mustacchi } 302*7fd79137SRobert Mustacchi ret = B_FALSE; 303*7fd79137SRobert Mustacchi 304*7fd79137SRobert Mustacchi out: 305*7fd79137SRobert Mustacchi ctf_free(iids, sizeof (ctf_id_t) * ifunc.ctc_argc); 306*7fd79137SRobert Mustacchi ctf_free(oids, sizeof (ctf_id_t) * ofunc.ctc_argc); 307*7fd79137SRobert Mustacchi return (ret); 308*7fd79137SRobert Mustacchi } 309*7fd79137SRobert Mustacchi 310*7fd79137SRobert Mustacchi /* 311*7fd79137SRobert Mustacchi * Two structures are the same if every member is identical to its corresponding 312*7fd79137SRobert Mustacchi * type, at the same offset, and has the same name, as well as them having the 313*7fd79137SRobert Mustacchi * same overall size. 314*7fd79137SRobert Mustacchi */ 315*7fd79137SRobert Mustacchi static int 316*7fd79137SRobert Mustacchi ctf_diff_struct(ctf_diff_t *cds, ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp, 317*7fd79137SRobert Mustacchi ctf_id_t oid) 318*7fd79137SRobert Mustacchi { 319*7fd79137SRobert Mustacchi ctf_file_t *oifp; 320*7fd79137SRobert Mustacchi const ctf_type_t *itp, *otp; 321*7fd79137SRobert Mustacchi ssize_t isize, iincr, osize, oincr; 322*7fd79137SRobert Mustacchi const ctf_member_t *imp, *omp; 323*7fd79137SRobert Mustacchi const ctf_lmember_t *ilmp, *olmp; 324*7fd79137SRobert Mustacchi int n; 325*7fd79137SRobert Mustacchi ctf_diff_guess_t *cdg; 326*7fd79137SRobert Mustacchi 327*7fd79137SRobert Mustacchi oifp = ifp; 328*7fd79137SRobert Mustacchi 329*7fd79137SRobert Mustacchi if ((itp = ctf_lookup_by_id(&ifp, iid)) == NULL) 330*7fd79137SRobert Mustacchi return (CTF_ERR); 331*7fd79137SRobert Mustacchi 332*7fd79137SRobert Mustacchi if ((otp = ctf_lookup_by_id(&ofp, oid)) == NULL) 333*7fd79137SRobert Mustacchi return (ctf_set_errno(oifp, ctf_errno(ofp))); 334*7fd79137SRobert Mustacchi 335*7fd79137SRobert Mustacchi if (ctf_type_size(ifp, iid) != ctf_type_size(ofp, oid)) 336*7fd79137SRobert Mustacchi return (B_TRUE); 337*7fd79137SRobert Mustacchi 338*7fd79137SRobert Mustacchi if (LCTF_INFO_VLEN(ifp, itp->ctt_info) != 339*7fd79137SRobert Mustacchi LCTF_INFO_VLEN(ofp, otp->ctt_info)) 340*7fd79137SRobert Mustacchi return (B_TRUE); 341*7fd79137SRobert Mustacchi 342*7fd79137SRobert Mustacchi (void) ctf_get_ctt_size(ifp, itp, &isize, &iincr); 343*7fd79137SRobert Mustacchi (void) ctf_get_ctt_size(ofp, otp, &osize, &oincr); 344*7fd79137SRobert Mustacchi 345*7fd79137SRobert Mustacchi if (ifp->ctf_version == CTF_VERSION_1 || isize < CTF_LSTRUCT_THRESH) { 346*7fd79137SRobert Mustacchi imp = (const ctf_member_t *)((uintptr_t)itp + iincr); 347*7fd79137SRobert Mustacchi ilmp = NULL; 348*7fd79137SRobert Mustacchi } else { 349*7fd79137SRobert Mustacchi imp = NULL; 350*7fd79137SRobert Mustacchi ilmp = (const ctf_lmember_t *)((uintptr_t)itp + iincr); 351*7fd79137SRobert Mustacchi } 352*7fd79137SRobert Mustacchi 353*7fd79137SRobert Mustacchi if (ofp->ctf_version == CTF_VERSION_1 || osize < CTF_LSTRUCT_THRESH) { 354*7fd79137SRobert Mustacchi omp = (const ctf_member_t *)((uintptr_t)otp + oincr); 355*7fd79137SRobert Mustacchi olmp = NULL; 356*7fd79137SRobert Mustacchi } else { 357*7fd79137SRobert Mustacchi omp = NULL; 358*7fd79137SRobert Mustacchi olmp = (const ctf_lmember_t *)((uintptr_t)otp + oincr); 359*7fd79137SRobert Mustacchi } 360*7fd79137SRobert Mustacchi 361*7fd79137SRobert Mustacchi /* 362*7fd79137SRobert Mustacchi * Insert our assumption that they're equal for the moment. 363*7fd79137SRobert Mustacchi */ 364*7fd79137SRobert Mustacchi cdg = ctf_alloc(sizeof (ctf_diff_guess_t)); 365*7fd79137SRobert Mustacchi if (cdg == NULL) 366*7fd79137SRobert Mustacchi return (ctf_set_errno(ifp, ENOMEM)); 367*7fd79137SRobert Mustacchi cdg->cdg_iid = iid; 368*7fd79137SRobert Mustacchi cdg->cdg_oid = oid; 369*7fd79137SRobert Mustacchi cdg->cdg_next = cds->cds_guess; 370*7fd79137SRobert Mustacchi cds->cds_guess = cdg; 371*7fd79137SRobert Mustacchi cds->cds_forward[TINDEX(iid)] = oid; 372*7fd79137SRobert Mustacchi cds->cds_reverse[TINDEX(oid)] = iid; 373*7fd79137SRobert Mustacchi 374*7fd79137SRobert Mustacchi for (n = LCTF_INFO_VLEN(ifp, itp->ctt_info); n != 0; n--) { 375*7fd79137SRobert Mustacchi const char *iname, *oname; 376*7fd79137SRobert Mustacchi ulong_t ioff, ooff; 377*7fd79137SRobert Mustacchi ctf_id_t itype, otype; 378*7fd79137SRobert Mustacchi int ret; 379*7fd79137SRobert Mustacchi 380*7fd79137SRobert Mustacchi if (imp != NULL) { 381*7fd79137SRobert Mustacchi iname = ctf_strptr(ifp, imp->ctm_name); 382*7fd79137SRobert Mustacchi ioff = imp->ctm_offset; 383*7fd79137SRobert Mustacchi itype = imp->ctm_type; 384*7fd79137SRobert Mustacchi } else { 385*7fd79137SRobert Mustacchi iname = ctf_strptr(ifp, ilmp->ctlm_name); 386*7fd79137SRobert Mustacchi ioff = CTF_LMEM_OFFSET(ilmp); 387*7fd79137SRobert Mustacchi itype = ilmp->ctlm_type; 388*7fd79137SRobert Mustacchi } 389*7fd79137SRobert Mustacchi 390*7fd79137SRobert Mustacchi if (omp != NULL) { 391*7fd79137SRobert Mustacchi oname = ctf_strptr(ofp, omp->ctm_name); 392*7fd79137SRobert Mustacchi ooff = omp->ctm_offset; 393*7fd79137SRobert Mustacchi otype = omp->ctm_type; 394*7fd79137SRobert Mustacchi } else { 395*7fd79137SRobert Mustacchi oname = ctf_strptr(ofp, olmp->ctlm_name); 396*7fd79137SRobert Mustacchi ooff = CTF_LMEM_OFFSET(olmp); 397*7fd79137SRobert Mustacchi otype = olmp->ctlm_type; 398*7fd79137SRobert Mustacchi } 399*7fd79137SRobert Mustacchi 400*7fd79137SRobert Mustacchi if (ioff != ooff) { 401*7fd79137SRobert Mustacchi return (B_TRUE); 402*7fd79137SRobert Mustacchi } 403*7fd79137SRobert Mustacchi if (strcmp(iname, oname) != 0) { 404*7fd79137SRobert Mustacchi return (B_TRUE); 405*7fd79137SRobert Mustacchi } 406*7fd79137SRobert Mustacchi ret = ctf_diff_type(cds, ifp, itype, ofp, otype); 407*7fd79137SRobert Mustacchi if (ret != B_FALSE) { 408*7fd79137SRobert Mustacchi return (ret); 409*7fd79137SRobert Mustacchi } 410*7fd79137SRobert Mustacchi 411*7fd79137SRobert Mustacchi /* Advance our pointers */ 412*7fd79137SRobert Mustacchi if (imp != NULL) 413*7fd79137SRobert Mustacchi imp++; 414*7fd79137SRobert Mustacchi if (ilmp != NULL) 415*7fd79137SRobert Mustacchi ilmp++; 416*7fd79137SRobert Mustacchi if (omp != NULL) 417*7fd79137SRobert Mustacchi omp++; 418*7fd79137SRobert Mustacchi if (olmp != NULL) 419*7fd79137SRobert Mustacchi olmp++; 420*7fd79137SRobert Mustacchi } 421*7fd79137SRobert Mustacchi 422*7fd79137SRobert Mustacchi return (B_FALSE); 423*7fd79137SRobert Mustacchi } 424*7fd79137SRobert Mustacchi 425*7fd79137SRobert Mustacchi /* 426*7fd79137SRobert Mustacchi * Two unions are the same if they have the same set of members. This is similar 427*7fd79137SRobert Mustacchi * to, but slightly different from a struct. The offsets of members don't 428*7fd79137SRobert Mustacchi * matter. However, there is no guarantee of ordering so we have to fall back to 429*7fd79137SRobert Mustacchi * doing an O(N^2) scan. 430*7fd79137SRobert Mustacchi */ 431*7fd79137SRobert Mustacchi typedef struct ctf_diff_union_member { 432*7fd79137SRobert Mustacchi ctf_diff_t *cdum_cds; 433*7fd79137SRobert Mustacchi ctf_file_t *cdum_fp; 434*7fd79137SRobert Mustacchi ctf_file_t *cdum_iterfp; 435*7fd79137SRobert Mustacchi const char *cdum_name; 436*7fd79137SRobert Mustacchi ctf_id_t cdum_type; 437*7fd79137SRobert Mustacchi int cdum_ret; 438*7fd79137SRobert Mustacchi } ctf_diff_union_member_t; 439*7fd79137SRobert Mustacchi 440*7fd79137SRobert Mustacchi typedef struct ctf_diff_union_fp { 441*7fd79137SRobert Mustacchi ctf_diff_t *cduf_cds; 442*7fd79137SRobert Mustacchi ctf_file_t *cduf_curfp; 443*7fd79137SRobert Mustacchi ctf_file_t *cduf_altfp; 444*7fd79137SRobert Mustacchi ctf_id_t cduf_type; 445*7fd79137SRobert Mustacchi int cduf_ret; 446*7fd79137SRobert Mustacchi } ctf_diff_union_fp_t; 447*7fd79137SRobert Mustacchi 448*7fd79137SRobert Mustacchi /* ARGSUSED */ 449*7fd79137SRobert Mustacchi static int 450*7fd79137SRobert Mustacchi ctf_diff_union_check_member(const char *name, ctf_id_t id, ulong_t off, 451*7fd79137SRobert Mustacchi void *arg) 452*7fd79137SRobert Mustacchi { 453*7fd79137SRobert Mustacchi int ret; 454*7fd79137SRobert Mustacchi ctf_diff_union_member_t *cdump = arg; 455*7fd79137SRobert Mustacchi 456*7fd79137SRobert Mustacchi if (strcmp(name, cdump->cdum_name) != 0) 457*7fd79137SRobert Mustacchi return (0); 458*7fd79137SRobert Mustacchi 459*7fd79137SRobert Mustacchi ret = ctf_diff_type(cdump->cdum_cds, cdump->cdum_fp, cdump->cdum_type, 460*7fd79137SRobert Mustacchi cdump->cdum_iterfp, id); 461*7fd79137SRobert Mustacchi if (ret == CTF_ERR) { 462*7fd79137SRobert Mustacchi cdump->cdum_ret = CTF_ERR; 463*7fd79137SRobert Mustacchi return (1); 464*7fd79137SRobert Mustacchi } 465*7fd79137SRobert Mustacchi 466*7fd79137SRobert Mustacchi if (ret == B_FALSE) { 467*7fd79137SRobert Mustacchi cdump->cdum_ret = B_FALSE; 468*7fd79137SRobert Mustacchi /* Return non-zero to stop iteration as we have a match */ 469*7fd79137SRobert Mustacchi return (1); 470*7fd79137SRobert Mustacchi } 471*7fd79137SRobert Mustacchi 472*7fd79137SRobert Mustacchi return (0); 473*7fd79137SRobert Mustacchi } 474*7fd79137SRobert Mustacchi 475*7fd79137SRobert Mustacchi /* ARGSUSED */ 476*7fd79137SRobert Mustacchi static int 477*7fd79137SRobert Mustacchi ctf_diff_union_check_fp(const char *name, ctf_id_t id, ulong_t off, void *arg) 478*7fd79137SRobert Mustacchi { 479*7fd79137SRobert Mustacchi int ret; 480*7fd79137SRobert Mustacchi ctf_diff_union_member_t cdum; 481*7fd79137SRobert Mustacchi ctf_diff_union_fp_t *cdufp = arg; 482*7fd79137SRobert Mustacchi 483*7fd79137SRobert Mustacchi cdum.cdum_cds = cdufp->cduf_cds; 484*7fd79137SRobert Mustacchi cdum.cdum_fp = cdufp->cduf_curfp; 485*7fd79137SRobert Mustacchi cdum.cdum_iterfp = cdufp->cduf_altfp; 486*7fd79137SRobert Mustacchi cdum.cdum_name = name; 487*7fd79137SRobert Mustacchi cdum.cdum_type = id; 488*7fd79137SRobert Mustacchi cdum.cdum_ret = B_TRUE; 489*7fd79137SRobert Mustacchi 490*7fd79137SRobert Mustacchi ret = ctf_member_iter(cdum.cdum_iterfp, cdufp->cduf_type, 491*7fd79137SRobert Mustacchi ctf_diff_union_check_member, &cdum); 492*7fd79137SRobert Mustacchi if (ret == 0 || cdum.cdum_ret == CTF_ERR) { 493*7fd79137SRobert Mustacchi /* No match found or error, terminate now */ 494*7fd79137SRobert Mustacchi cdufp->cduf_ret = cdum.cdum_ret; 495*7fd79137SRobert Mustacchi return (1); 496*7fd79137SRobert Mustacchi } else if (ret == CTF_ERR) { 497*7fd79137SRobert Mustacchi (void) ctf_set_errno(cdum.cdum_fp, ctf_errno(cdum.cdum_iterfp)); 498*7fd79137SRobert Mustacchi cdufp->cduf_ret = CTF_ERR; 499*7fd79137SRobert Mustacchi return (1); 500*7fd79137SRobert Mustacchi } else { 501*7fd79137SRobert Mustacchi ASSERT(cdum.cdum_ret == B_FALSE); 502*7fd79137SRobert Mustacchi cdufp->cduf_ret = cdum.cdum_ret; 503*7fd79137SRobert Mustacchi return (0); 504*7fd79137SRobert Mustacchi } 505*7fd79137SRobert Mustacchi } 506*7fd79137SRobert Mustacchi 507*7fd79137SRobert Mustacchi static int 508*7fd79137SRobert Mustacchi ctf_diff_union(ctf_diff_t *cds, ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp, 509*7fd79137SRobert Mustacchi ctf_id_t oid) 510*7fd79137SRobert Mustacchi { 511*7fd79137SRobert Mustacchi ctf_file_t *oifp; 512*7fd79137SRobert Mustacchi const ctf_type_t *itp, *otp; 513*7fd79137SRobert Mustacchi ctf_diff_union_fp_t cduf; 514*7fd79137SRobert Mustacchi ctf_diff_guess_t *cdg; 515*7fd79137SRobert Mustacchi int ret; 516*7fd79137SRobert Mustacchi 517*7fd79137SRobert Mustacchi oifp = ifp; 518*7fd79137SRobert Mustacchi if ((itp = ctf_lookup_by_id(&ifp, iid)) == NULL) 519*7fd79137SRobert Mustacchi return (CTF_ERR); 520*7fd79137SRobert Mustacchi if ((otp = ctf_lookup_by_id(&ofp, oid)) == NULL) 521*7fd79137SRobert Mustacchi return (ctf_set_errno(oifp, ctf_errno(ofp))); 522*7fd79137SRobert Mustacchi 523*7fd79137SRobert Mustacchi if (LCTF_INFO_VLEN(ifp, itp->ctt_info) != 524*7fd79137SRobert Mustacchi LCTF_INFO_VLEN(ofp, otp->ctt_info)) 525*7fd79137SRobert Mustacchi return (B_TRUE); 526*7fd79137SRobert Mustacchi 527*7fd79137SRobert Mustacchi cdg = ctf_alloc(sizeof (ctf_diff_guess_t)); 528*7fd79137SRobert Mustacchi if (cdg == NULL) 529*7fd79137SRobert Mustacchi return (ctf_set_errno(ifp, ENOMEM)); 530*7fd79137SRobert Mustacchi cdg->cdg_iid = iid; 531*7fd79137SRobert Mustacchi cdg->cdg_oid = oid; 532*7fd79137SRobert Mustacchi cdg->cdg_next = cds->cds_guess; 533*7fd79137SRobert Mustacchi cds->cds_guess = cdg; 534*7fd79137SRobert Mustacchi cds->cds_forward[TINDEX(iid)] = oid; 535*7fd79137SRobert Mustacchi cds->cds_reverse[TINDEX(oid)] = iid; 536*7fd79137SRobert Mustacchi 537*7fd79137SRobert Mustacchi cduf.cduf_cds = cds; 538*7fd79137SRobert Mustacchi cduf.cduf_curfp = ifp; 539*7fd79137SRobert Mustacchi cduf.cduf_altfp = ofp; 540*7fd79137SRobert Mustacchi cduf.cduf_type = oid; 541*7fd79137SRobert Mustacchi cduf.cduf_ret = B_TRUE; 542*7fd79137SRobert Mustacchi ret = ctf_member_iter(ifp, iid, ctf_diff_union_check_fp, &cduf); 543*7fd79137SRobert Mustacchi if (ret != CTF_ERR) 544*7fd79137SRobert Mustacchi ret = cduf.cduf_ret; 545*7fd79137SRobert Mustacchi 546*7fd79137SRobert Mustacchi return (ret); 547*7fd79137SRobert Mustacchi } 548*7fd79137SRobert Mustacchi 549*7fd79137SRobert Mustacchi /* 550*7fd79137SRobert Mustacchi * Two enums are equivalent if they share the same underlying type and they have 551*7fd79137SRobert Mustacchi * the same set of members. 552*7fd79137SRobert Mustacchi */ 553*7fd79137SRobert Mustacchi static int 554*7fd79137SRobert Mustacchi ctf_diff_enum(ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp, ctf_id_t oid) 555*7fd79137SRobert Mustacchi { 556*7fd79137SRobert Mustacchi ctf_file_t *oifp; 557*7fd79137SRobert Mustacchi const ctf_type_t *itp, *otp; 558*7fd79137SRobert Mustacchi ssize_t iincr, oincr; 559*7fd79137SRobert Mustacchi const ctf_enum_t *iep, *oep; 560*7fd79137SRobert Mustacchi int n; 561*7fd79137SRobert Mustacchi 562*7fd79137SRobert Mustacchi oifp = ifp; 563*7fd79137SRobert Mustacchi if ((itp = ctf_lookup_by_id(&ifp, iid)) == NULL) 564*7fd79137SRobert Mustacchi return (CTF_ERR); 565*7fd79137SRobert Mustacchi if ((otp = ctf_lookup_by_id(&ofp, oid)) == NULL) 566*7fd79137SRobert Mustacchi return (ctf_set_errno(oifp, ctf_errno(ofp))); 567*7fd79137SRobert Mustacchi 568*7fd79137SRobert Mustacchi if (LCTF_INFO_VLEN(ifp, itp->ctt_info) != 569*7fd79137SRobert Mustacchi LCTF_INFO_VLEN(ofp, otp->ctt_info)) 570*7fd79137SRobert Mustacchi return (B_TRUE); 571*7fd79137SRobert Mustacchi 572*7fd79137SRobert Mustacchi (void) ctf_get_ctt_size(ifp, itp, NULL, &iincr); 573*7fd79137SRobert Mustacchi (void) ctf_get_ctt_size(ofp, otp, NULL, &oincr); 574*7fd79137SRobert Mustacchi iep = (const ctf_enum_t *)((uintptr_t)itp + iincr); 575*7fd79137SRobert Mustacchi oep = (const ctf_enum_t *)((uintptr_t)otp + oincr); 576*7fd79137SRobert Mustacchi 577*7fd79137SRobert Mustacchi for (n = LCTF_INFO_VLEN(ifp, itp->ctt_info); n != 0; 578*7fd79137SRobert Mustacchi n--, iep++, oep++) { 579*7fd79137SRobert Mustacchi if (strcmp(ctf_strptr(ifp, iep->cte_name), 580*7fd79137SRobert Mustacchi ctf_strptr(ofp, oep->cte_name)) != 0) 581*7fd79137SRobert Mustacchi return (B_TRUE); 582*7fd79137SRobert Mustacchi 583*7fd79137SRobert Mustacchi if (iep->cte_value != oep->cte_value) 584*7fd79137SRobert Mustacchi return (B_TRUE); 585*7fd79137SRobert Mustacchi } 586*7fd79137SRobert Mustacchi 587*7fd79137SRobert Mustacchi return (B_FALSE); 588*7fd79137SRobert Mustacchi } 589*7fd79137SRobert Mustacchi 590*7fd79137SRobert Mustacchi /* 591*7fd79137SRobert Mustacchi * Two forwards are equivalent in one of two cases. If both are forwards, than 592*7fd79137SRobert Mustacchi * they are the same. Otherwise, they're equivalent if one is a struct or union 593*7fd79137SRobert Mustacchi * and the other is a forward. 594*7fd79137SRobert Mustacchi */ 595*7fd79137SRobert Mustacchi static int 596*7fd79137SRobert Mustacchi ctf_diff_forward(ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp, ctf_id_t oid) 597*7fd79137SRobert Mustacchi { 598*7fd79137SRobert Mustacchi int ikind, okind; 599*7fd79137SRobert Mustacchi 600*7fd79137SRobert Mustacchi ikind = ctf_type_kind(ifp, iid); 601*7fd79137SRobert Mustacchi okind = ctf_type_kind(ofp, oid); 602*7fd79137SRobert Mustacchi 603*7fd79137SRobert Mustacchi if (ikind == okind) { 604*7fd79137SRobert Mustacchi ASSERT(ikind == CTF_K_FORWARD); 605*7fd79137SRobert Mustacchi return (B_FALSE); 606*7fd79137SRobert Mustacchi } else if (ikind == CTF_K_FORWARD) { 607*7fd79137SRobert Mustacchi return (okind != CTF_K_UNION && okind != CTF_K_STRUCT); 608*7fd79137SRobert Mustacchi } else { 609*7fd79137SRobert Mustacchi return (ikind != CTF_K_UNION && ikind != CTF_K_STRUCT); 610*7fd79137SRobert Mustacchi } 611*7fd79137SRobert Mustacchi } 612*7fd79137SRobert Mustacchi 613*7fd79137SRobert Mustacchi /* 614*7fd79137SRobert Mustacchi * Are two types equivalent? 615*7fd79137SRobert Mustacchi */ 616*7fd79137SRobert Mustacchi int 617*7fd79137SRobert Mustacchi ctf_diff_type(ctf_diff_t *cds, ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp, 618*7fd79137SRobert Mustacchi ctf_id_t oid) 619*7fd79137SRobert Mustacchi { 620*7fd79137SRobert Mustacchi int ret, ikind, okind; 621*7fd79137SRobert Mustacchi 622*7fd79137SRobert Mustacchi /* Do a quick short circuit */ 623*7fd79137SRobert Mustacchi if (ifp == ofp && iid == oid) 624*7fd79137SRobert Mustacchi return (B_FALSE); 625*7fd79137SRobert Mustacchi 626*7fd79137SRobert Mustacchi /* 627*7fd79137SRobert Mustacchi * Check if it's something we've already encountered in a forward 628*7fd79137SRobert Mustacchi * reference or forward negative table. Also double check the reverse 629*7fd79137SRobert Mustacchi * table. 630*7fd79137SRobert Mustacchi */ 631*7fd79137SRobert Mustacchi if (cds->cds_forward[TINDEX(iid)] == oid) 632*7fd79137SRobert Mustacchi return (B_FALSE); 633*7fd79137SRobert Mustacchi if (cds->cds_forward[TINDEX(iid)] != 0) 634*7fd79137SRobert Mustacchi return (B_TRUE); 635*7fd79137SRobert Mustacchi if (cds->cds_reverse[TINDEX(oid)] == iid) 636*7fd79137SRobert Mustacchi return (B_FALSE); 637*7fd79137SRobert Mustacchi if ((cds->cds_flags & CTF_DIFF_F_IGNORE_INTNAMES) == 0 && 638*7fd79137SRobert Mustacchi cds->cds_reverse[TINDEX(oid)] != 0) 639*7fd79137SRobert Mustacchi return (B_TRUE); 640*7fd79137SRobert Mustacchi 641*7fd79137SRobert Mustacchi ikind = ctf_type_kind(ifp, iid); 642*7fd79137SRobert Mustacchi okind = ctf_type_kind(ofp, oid); 643*7fd79137SRobert Mustacchi 644*7fd79137SRobert Mustacchi if (ikind != okind && 645*7fd79137SRobert Mustacchi ikind != CTF_K_FORWARD && okind != CTF_K_FORWARD) 646*7fd79137SRobert Mustacchi return (B_TRUE); 647*7fd79137SRobert Mustacchi 648*7fd79137SRobert Mustacchi /* Check names */ 649*7fd79137SRobert Mustacchi if ((ret = ctf_diff_name(ifp, iid, ofp, oid)) != B_FALSE) { 650*7fd79137SRobert Mustacchi if (ikind != okind || ikind != CTF_K_INTEGER || 651*7fd79137SRobert Mustacchi (cds->cds_flags & CTF_DIFF_F_IGNORE_INTNAMES) == 0) 652*7fd79137SRobert Mustacchi return (ret); 653*7fd79137SRobert Mustacchi } 654*7fd79137SRobert Mustacchi 655*7fd79137SRobert Mustacchi if (ikind == CTF_K_FORWARD || okind == CTF_K_FORWARD) 656*7fd79137SRobert Mustacchi return (ctf_diff_forward(ifp, iid, ofp, oid)); 657*7fd79137SRobert Mustacchi 658*7fd79137SRobert Mustacchi switch (ikind) { 659*7fd79137SRobert Mustacchi case CTF_K_INTEGER: 660*7fd79137SRobert Mustacchi case CTF_K_FLOAT: 661*7fd79137SRobert Mustacchi ret = ctf_diff_number(ifp, iid, ofp, oid); 662*7fd79137SRobert Mustacchi break; 663*7fd79137SRobert Mustacchi case CTF_K_ARRAY: 664*7fd79137SRobert Mustacchi ret = ctf_diff_array(cds, ifp, iid, ofp, oid); 665*7fd79137SRobert Mustacchi break; 666*7fd79137SRobert Mustacchi case CTF_K_FUNCTION: 667*7fd79137SRobert Mustacchi ret = ctf_diff_fptr(cds, ifp, iid, ofp, oid); 668*7fd79137SRobert Mustacchi break; 669*7fd79137SRobert Mustacchi case CTF_K_STRUCT: 670*7fd79137SRobert Mustacchi ret = ctf_diff_struct(cds, ifp, iid, ofp, oid); 671*7fd79137SRobert Mustacchi break; 672*7fd79137SRobert Mustacchi case CTF_K_UNION: 673*7fd79137SRobert Mustacchi ret = ctf_diff_union(cds, ifp, iid, ofp, oid); 674*7fd79137SRobert Mustacchi break; 675*7fd79137SRobert Mustacchi case CTF_K_ENUM: 676*7fd79137SRobert Mustacchi ret = ctf_diff_enum(ifp, iid, ofp, oid); 677*7fd79137SRobert Mustacchi break; 678*7fd79137SRobert Mustacchi case CTF_K_FORWARD: 679*7fd79137SRobert Mustacchi ret = ctf_diff_forward(ifp, iid, ofp, oid); 680*7fd79137SRobert Mustacchi break; 681*7fd79137SRobert Mustacchi case CTF_K_TYPEDEF: 682*7fd79137SRobert Mustacchi ret = ctf_diff_typedef(cds, ifp, iid, ofp, oid); 683*7fd79137SRobert Mustacchi break; 684*7fd79137SRobert Mustacchi case CTF_K_POINTER: 685*7fd79137SRobert Mustacchi case CTF_K_VOLATILE: 686*7fd79137SRobert Mustacchi case CTF_K_CONST: 687*7fd79137SRobert Mustacchi case CTF_K_RESTRICT: 688*7fd79137SRobert Mustacchi ret = ctf_diff_qualifier(cds, ifp, iid, ofp, oid); 689*7fd79137SRobert Mustacchi break; 690*7fd79137SRobert Mustacchi case CTF_K_UNKNOWN: 691*7fd79137SRobert Mustacchi /* 692*7fd79137SRobert Mustacchi * The current CTF tools use CTF_K_UNKNOWN as a padding type. We 693*7fd79137SRobert Mustacchi * always declare two instances of CTF_K_UNKNOWN as different, 694*7fd79137SRobert Mustacchi * even though this leads to additional diff noise. 695*7fd79137SRobert Mustacchi */ 696*7fd79137SRobert Mustacchi ret = B_TRUE; 697*7fd79137SRobert Mustacchi break; 698*7fd79137SRobert Mustacchi default: 699*7fd79137SRobert Mustacchi abort(); 700*7fd79137SRobert Mustacchi } 701*7fd79137SRobert Mustacchi 702*7fd79137SRobert Mustacchi return (ret); 703*7fd79137SRobert Mustacchi } 704*7fd79137SRobert Mustacchi 705*7fd79137SRobert Mustacchi /* 706*7fd79137SRobert Mustacchi * Walk every type in the first container and try to find a match in the second. 707*7fd79137SRobert Mustacchi * If there is a match, then update both the forward and reverse mapping tables. 708*7fd79137SRobert Mustacchi * 709*7fd79137SRobert Mustacchi * The self variable tells us whether or not we should be comparing the input 710*7fd79137SRobert Mustacchi * ctf container with itself or not. 711*7fd79137SRobert Mustacchi */ 712*7fd79137SRobert Mustacchi static int 713*7fd79137SRobert Mustacchi ctf_diff_pass1(ctf_diff_t *cds, boolean_t self) 714*7fd79137SRobert Mustacchi { 715*7fd79137SRobert Mustacchi int i, j, diff; 716*7fd79137SRobert Mustacchi int istart, iend, jstart, jend; 717*7fd79137SRobert Mustacchi 718*7fd79137SRobert Mustacchi istart = 1; 719*7fd79137SRobert Mustacchi iend = cds->cds_ifp->ctf_typemax; 720*7fd79137SRobert Mustacchi if (cds->cds_ifp->ctf_flags & LCTF_CHILD) { 721*7fd79137SRobert Mustacchi istart += CTF_CHILD_START; 722*7fd79137SRobert Mustacchi iend += CTF_CHILD_START; 723*7fd79137SRobert Mustacchi } 724*7fd79137SRobert Mustacchi 725*7fd79137SRobert Mustacchi jstart = 1; 726*7fd79137SRobert Mustacchi jend = cds->cds_ofp->ctf_typemax; 727*7fd79137SRobert Mustacchi if (cds->cds_ofp->ctf_flags & LCTF_CHILD) { 728*7fd79137SRobert Mustacchi jstart += CTF_CHILD_START; 729*7fd79137SRobert Mustacchi jend += CTF_CHILD_START; 730*7fd79137SRobert Mustacchi } 731*7fd79137SRobert Mustacchi 732*7fd79137SRobert Mustacchi for (i = istart; i <= iend; i++) { 733*7fd79137SRobert Mustacchi diff = B_TRUE; 734*7fd79137SRobert Mustacchi 735*7fd79137SRobert Mustacchi /* 736*7fd79137SRobert Mustacchi * If we're doing a self diff for dedup purposes, then we want 737*7fd79137SRobert Mustacchi * to ensure that we compare a type i with every type in the 738*7fd79137SRobert Mustacchi * range, [ 1, i ). Yes, this does mean that when i equals 1, 739*7fd79137SRobert Mustacchi * we won't compare anything. 740*7fd79137SRobert Mustacchi */ 741*7fd79137SRobert Mustacchi if (self == B_TRUE) { 742*7fd79137SRobert Mustacchi jstart = istart; 743*7fd79137SRobert Mustacchi jend = i - 1; 744*7fd79137SRobert Mustacchi } 745*7fd79137SRobert Mustacchi for (j = jstart; j <= jend; j++) { 746*7fd79137SRobert Mustacchi ctf_diff_guess_t *cdg, *tofree; 747*7fd79137SRobert Mustacchi 748*7fd79137SRobert Mustacchi ASSERT(cds->cds_guess == NULL); 749*7fd79137SRobert Mustacchi diff = ctf_diff_type(cds, cds->cds_ifp, i, 750*7fd79137SRobert Mustacchi cds->cds_ofp, j); 751*7fd79137SRobert Mustacchi if (diff == CTF_ERR) 752*7fd79137SRobert Mustacchi return (CTF_ERR); 753*7fd79137SRobert Mustacchi 754*7fd79137SRobert Mustacchi /* Clean up our guesses */ 755*7fd79137SRobert Mustacchi cdg = cds->cds_guess; 756*7fd79137SRobert Mustacchi cds->cds_guess = NULL; 757*7fd79137SRobert Mustacchi while (cdg != NULL) { 758*7fd79137SRobert Mustacchi if (diff == B_TRUE) { 759*7fd79137SRobert Mustacchi cds->cds_forward[TINDEX(cdg->cdg_iid)] = 760*7fd79137SRobert Mustacchi 0; 761*7fd79137SRobert Mustacchi cds->cds_reverse[TINDEX(cdg->cdg_oid)] = 762*7fd79137SRobert Mustacchi 0; 763*7fd79137SRobert Mustacchi } 764*7fd79137SRobert Mustacchi tofree = cdg; 765*7fd79137SRobert Mustacchi cdg = cdg->cdg_next; 766*7fd79137SRobert Mustacchi ctf_free(tofree, sizeof (ctf_diff_guess_t)); 767*7fd79137SRobert Mustacchi } 768*7fd79137SRobert Mustacchi 769*7fd79137SRobert Mustacchi /* Found a hit, update the tables */ 770*7fd79137SRobert Mustacchi if (diff == B_FALSE) { 771*7fd79137SRobert Mustacchi cds->cds_forward[TINDEX(i)] = j; 772*7fd79137SRobert Mustacchi if (cds->cds_reverse[TINDEX(j)] == 0) 773*7fd79137SRobert Mustacchi cds->cds_reverse[TINDEX(j)] = i; 774*7fd79137SRobert Mustacchi break; 775*7fd79137SRobert Mustacchi } 776*7fd79137SRobert Mustacchi } 777*7fd79137SRobert Mustacchi 778*7fd79137SRobert Mustacchi /* Call the callback at this point */ 779*7fd79137SRobert Mustacchi if (diff == B_TRUE) { 780*7fd79137SRobert Mustacchi cds->cds_forward[TINDEX(i)] = CTF_ERR; 781*7fd79137SRobert Mustacchi cds->cds_func(cds->cds_ifp, i, B_FALSE, NULL, CTF_ERR, 782*7fd79137SRobert Mustacchi cds->cds_arg); 783*7fd79137SRobert Mustacchi } else { 784*7fd79137SRobert Mustacchi cds->cds_func(cds->cds_ifp, i, B_TRUE, cds->cds_ofp, j, 785*7fd79137SRobert Mustacchi cds->cds_arg); 786*7fd79137SRobert Mustacchi } 787*7fd79137SRobert Mustacchi } 788*7fd79137SRobert Mustacchi 789*7fd79137SRobert Mustacchi return (0); 790*7fd79137SRobert Mustacchi } 791*7fd79137SRobert Mustacchi 792*7fd79137SRobert Mustacchi /* 793*7fd79137SRobert Mustacchi * Now we need to walk the second container and emit anything that we didn't 794*7fd79137SRobert Mustacchi * find as common in the first pass. 795*7fd79137SRobert Mustacchi */ 796*7fd79137SRobert Mustacchi static int 797*7fd79137SRobert Mustacchi ctf_diff_pass2(ctf_diff_t *cds) 798*7fd79137SRobert Mustacchi { 799*7fd79137SRobert Mustacchi int i, start, end; 800*7fd79137SRobert Mustacchi 801*7fd79137SRobert Mustacchi start = 0x1; 802*7fd79137SRobert Mustacchi end = cds->cds_ofp->ctf_typemax; 803*7fd79137SRobert Mustacchi if (cds->cds_ofp->ctf_flags & LCTF_CHILD) { 804*7fd79137SRobert Mustacchi start += CTF_CHILD_START; 805*7fd79137SRobert Mustacchi end += CTF_CHILD_START; 806*7fd79137SRobert Mustacchi } 807*7fd79137SRobert Mustacchi 808*7fd79137SRobert Mustacchi for (i = start; i <= end; i++) { 809*7fd79137SRobert Mustacchi if (cds->cds_reverse[TINDEX(i)] != 0) 810*7fd79137SRobert Mustacchi continue; 811*7fd79137SRobert Mustacchi cds->cds_func(cds->cds_ofp, i, B_FALSE, NULL, CTF_ERR, 812*7fd79137SRobert Mustacchi cds->cds_arg); 813*7fd79137SRobert Mustacchi } 814*7fd79137SRobert Mustacchi 815*7fd79137SRobert Mustacchi return (0); 816*7fd79137SRobert Mustacchi } 817*7fd79137SRobert Mustacchi 818*7fd79137SRobert Mustacchi int 819*7fd79137SRobert Mustacchi ctf_diff_init(ctf_file_t *ifp, ctf_file_t *ofp, ctf_diff_t **cdsp) 820*7fd79137SRobert Mustacchi { 821*7fd79137SRobert Mustacchi ctf_diff_t *cds; 822*7fd79137SRobert Mustacchi size_t fsize, rsize; 823*7fd79137SRobert Mustacchi 824*7fd79137SRobert Mustacchi cds = ctf_alloc(sizeof (ctf_diff_t)); 825*7fd79137SRobert Mustacchi if (cds == NULL) 826*7fd79137SRobert Mustacchi return (ctf_set_errno(ifp, ENOMEM)); 827*7fd79137SRobert Mustacchi 828*7fd79137SRobert Mustacchi bzero(cds, sizeof (ctf_diff_t)); 829*7fd79137SRobert Mustacchi cds->cds_ifp = ifp; 830*7fd79137SRobert Mustacchi cds->cds_ofp = ofp; 831*7fd79137SRobert Mustacchi 832*7fd79137SRobert Mustacchi fsize = sizeof (ctf_id_t) * ifp->ctf_typemax; 833*7fd79137SRobert Mustacchi rsize = sizeof (ctf_id_t) * ofp->ctf_typemax; 834*7fd79137SRobert Mustacchi if (ifp->ctf_flags & LCTF_CHILD) 835*7fd79137SRobert Mustacchi fsize += CTF_CHILD_START * sizeof (ctf_id_t); 836*7fd79137SRobert Mustacchi if (ofp->ctf_flags & LCTF_CHILD) 837*7fd79137SRobert Mustacchi rsize += CTF_CHILD_START * sizeof (ctf_id_t); 838*7fd79137SRobert Mustacchi 839*7fd79137SRobert Mustacchi cds->cds_forward = ctf_alloc(fsize); 840*7fd79137SRobert Mustacchi if (cds->cds_forward == NULL) { 841*7fd79137SRobert Mustacchi ctf_free(cds, sizeof (ctf_diff_t)); 842*7fd79137SRobert Mustacchi return (ctf_set_errno(ifp, ENOMEM)); 843*7fd79137SRobert Mustacchi } 844*7fd79137SRobert Mustacchi cds->cds_fsize = fsize; 845*7fd79137SRobert Mustacchi cds->cds_reverse = ctf_alloc(rsize); 846*7fd79137SRobert Mustacchi if (cds->cds_reverse == NULL) { 847*7fd79137SRobert Mustacchi ctf_free(cds->cds_forward, fsize); 848*7fd79137SRobert Mustacchi ctf_free(cds, sizeof (ctf_diff_t)); 849*7fd79137SRobert Mustacchi return (ctf_set_errno(ifp, ENOMEM)); 850*7fd79137SRobert Mustacchi } 851*7fd79137SRobert Mustacchi cds->cds_rsize = rsize; 852*7fd79137SRobert Mustacchi bzero(cds->cds_forward, fsize); 853*7fd79137SRobert Mustacchi bzero(cds->cds_reverse, rsize); 854*7fd79137SRobert Mustacchi 855*7fd79137SRobert Mustacchi cds->cds_ifp->ctf_refcnt++; 856*7fd79137SRobert Mustacchi cds->cds_ofp->ctf_refcnt++; 857*7fd79137SRobert Mustacchi *cdsp = cds; 858*7fd79137SRobert Mustacchi return (0); 859*7fd79137SRobert Mustacchi } 860*7fd79137SRobert Mustacchi 861*7fd79137SRobert Mustacchi int 862*7fd79137SRobert Mustacchi ctf_diff_types(ctf_diff_t *cds, ctf_diff_type_f cb, void *arg) 863*7fd79137SRobert Mustacchi { 864*7fd79137SRobert Mustacchi int ret; 865*7fd79137SRobert Mustacchi 866*7fd79137SRobert Mustacchi cds->cds_func = cb; 867*7fd79137SRobert Mustacchi cds->cds_arg = arg; 868*7fd79137SRobert Mustacchi 869*7fd79137SRobert Mustacchi ret = ctf_diff_pass1(cds, B_FALSE); 870*7fd79137SRobert Mustacchi if (ret == 0) 871*7fd79137SRobert Mustacchi ret = ctf_diff_pass2(cds); 872*7fd79137SRobert Mustacchi 873*7fd79137SRobert Mustacchi cds->cds_func = NULL; 874*7fd79137SRobert Mustacchi cds->cds_arg = NULL; 875*7fd79137SRobert Mustacchi cds->cds_tvalid = B_TRUE; 876*7fd79137SRobert Mustacchi return (ret); 877*7fd79137SRobert Mustacchi } 878*7fd79137SRobert Mustacchi 879*7fd79137SRobert Mustacchi /* 880*7fd79137SRobert Mustacchi * Do a diff where we're comparing a container with itself. In other words we'd 881*7fd79137SRobert Mustacchi * like to know what types are actually duplicates of existing types in the 882*7fd79137SRobert Mustacchi * container. 883*7fd79137SRobert Mustacchi * 884*7fd79137SRobert Mustacchi * Note this should remain private to libctf and not be exported in the public 885*7fd79137SRobert Mustacchi * mapfile for the time being. 886*7fd79137SRobert Mustacchi */ 887*7fd79137SRobert Mustacchi int 888*7fd79137SRobert Mustacchi ctf_diff_self(ctf_diff_t *cds, ctf_diff_type_f cb, void *arg) 889*7fd79137SRobert Mustacchi { 890*7fd79137SRobert Mustacchi if (cds->cds_ifp != cds->cds_ofp) 891*7fd79137SRobert Mustacchi return (EINVAL); 892*7fd79137SRobert Mustacchi 893*7fd79137SRobert Mustacchi cds->cds_func = cb; 894*7fd79137SRobert Mustacchi cds->cds_arg = arg; 895*7fd79137SRobert Mustacchi 896*7fd79137SRobert Mustacchi return (ctf_diff_pass1(cds, B_TRUE)); 897*7fd79137SRobert Mustacchi } 898*7fd79137SRobert Mustacchi 899*7fd79137SRobert Mustacchi 900*7fd79137SRobert Mustacchi void 901*7fd79137SRobert Mustacchi ctf_diff_fini(ctf_diff_t *cds) 902*7fd79137SRobert Mustacchi { 903*7fd79137SRobert Mustacchi ctf_diff_guess_t *cdg; 904*7fd79137SRobert Mustacchi size_t fsize, rsize; 905*7fd79137SRobert Mustacchi 906*7fd79137SRobert Mustacchi if (cds == NULL) 907*7fd79137SRobert Mustacchi return; 908*7fd79137SRobert Mustacchi 909*7fd79137SRobert Mustacchi cds->cds_ifp->ctf_refcnt--; 910*7fd79137SRobert Mustacchi cds->cds_ofp->ctf_refcnt--; 911*7fd79137SRobert Mustacchi 912*7fd79137SRobert Mustacchi fsize = sizeof (ctf_id_t) * cds->cds_ifp->ctf_typemax; 913*7fd79137SRobert Mustacchi rsize = sizeof (ctf_id_t) * cds->cds_ofp->ctf_typemax; 914*7fd79137SRobert Mustacchi if (cds->cds_ifp->ctf_flags & LCTF_CHILD) 915*7fd79137SRobert Mustacchi fsize += CTF_CHILD_START * sizeof (ctf_id_t); 916*7fd79137SRobert Mustacchi if (cds->cds_ofp->ctf_flags & LCTF_CHILD) 917*7fd79137SRobert Mustacchi rsize += CTF_CHILD_START * sizeof (ctf_id_t); 918*7fd79137SRobert Mustacchi 919*7fd79137SRobert Mustacchi if (cds->cds_ifuncs != NULL) 920*7fd79137SRobert Mustacchi ctf_free(cds->cds_ifuncs, 921*7fd79137SRobert Mustacchi sizeof (ctf_diff_func_t) * cds->cds_nifuncs); 922*7fd79137SRobert Mustacchi if (cds->cds_ofuncs != NULL) 923*7fd79137SRobert Mustacchi ctf_free(cds->cds_ofuncs, 924*7fd79137SRobert Mustacchi sizeof (ctf_diff_func_t) * cds->cds_nofuncs); 925*7fd79137SRobert Mustacchi if (cds->cds_iobj != NULL) 926*7fd79137SRobert Mustacchi ctf_free(cds->cds_iobj, 927*7fd79137SRobert Mustacchi sizeof (ctf_diff_obj_t) * cds->cds_niobj); 928*7fd79137SRobert Mustacchi if (cds->cds_oobj != NULL) 929*7fd79137SRobert Mustacchi ctf_free(cds->cds_oobj, 930*7fd79137SRobert Mustacchi sizeof (ctf_diff_obj_t) * cds->cds_noobj); 931*7fd79137SRobert Mustacchi cdg = cds->cds_guess; 932*7fd79137SRobert Mustacchi while (cdg != NULL) { 933*7fd79137SRobert Mustacchi ctf_diff_guess_t *tofree = cdg; 934*7fd79137SRobert Mustacchi cdg = cdg->cdg_next; 935*7fd79137SRobert Mustacchi ctf_free(tofree, sizeof (ctf_diff_guess_t)); 936*7fd79137SRobert Mustacchi } 937*7fd79137SRobert Mustacchi if (cds->cds_forward != NULL) 938*7fd79137SRobert Mustacchi ctf_free(cds->cds_forward, cds->cds_fsize); 939*7fd79137SRobert Mustacchi if (cds->cds_reverse != NULL) 940*7fd79137SRobert Mustacchi ctf_free(cds->cds_reverse, cds->cds_rsize); 941*7fd79137SRobert Mustacchi ctf_free(cds, sizeof (ctf_diff_t)); 942*7fd79137SRobert Mustacchi } 943*7fd79137SRobert Mustacchi 944*7fd79137SRobert Mustacchi uint_t 945*7fd79137SRobert Mustacchi ctf_diff_getflags(ctf_diff_t *cds) 946*7fd79137SRobert Mustacchi { 947*7fd79137SRobert Mustacchi return (cds->cds_flags); 948*7fd79137SRobert Mustacchi } 949*7fd79137SRobert Mustacchi 950*7fd79137SRobert Mustacchi int 951*7fd79137SRobert Mustacchi ctf_diff_setflags(ctf_diff_t *cds, uint_t flags) 952*7fd79137SRobert Mustacchi { 953*7fd79137SRobert Mustacchi if ((flags & ~CTF_DIFF_F_IGNORE_INTNAMES) != 0) 954*7fd79137SRobert Mustacchi return (ctf_set_errno(cds->cds_ifp, EINVAL)); 955*7fd79137SRobert Mustacchi 956*7fd79137SRobert Mustacchi cds->cds_flags = flags; 957*7fd79137SRobert Mustacchi return (0); 958*7fd79137SRobert Mustacchi } 959*7fd79137SRobert Mustacchi 960*7fd79137SRobert Mustacchi static boolean_t 961*7fd79137SRobert Mustacchi ctf_diff_symid(ctf_diff_t *cds, ctf_id_t iid, ctf_id_t oid) 962*7fd79137SRobert Mustacchi { 963*7fd79137SRobert Mustacchi ctf_file_t *ifp, *ofp; 964*7fd79137SRobert Mustacchi 965*7fd79137SRobert Mustacchi ifp = cds->cds_ifp; 966*7fd79137SRobert Mustacchi ofp = cds->cds_ofp; 967*7fd79137SRobert Mustacchi 968*7fd79137SRobert Mustacchi /* 969*7fd79137SRobert Mustacchi * If we have parent containers on the scene here, we need to go through 970*7fd79137SRobert Mustacchi * and do a full diff check because a diff for types will not actually 971*7fd79137SRobert Mustacchi * go through and check types in the parent container. 972*7fd79137SRobert Mustacchi */ 973*7fd79137SRobert Mustacchi if (iid == 0 || oid == 0) 974*7fd79137SRobert Mustacchi return (iid == oid ? B_FALSE: B_TRUE); 975*7fd79137SRobert Mustacchi 976*7fd79137SRobert Mustacchi if (!(ifp->ctf_flags & LCTF_CHILD) && !(ofp->ctf_flags & LCTF_CHILD)) { 977*7fd79137SRobert Mustacchi if (cds->cds_forward[TINDEX(iid)] != oid) 978*7fd79137SRobert Mustacchi return (B_TRUE); 979*7fd79137SRobert Mustacchi return (B_FALSE); 980*7fd79137SRobert Mustacchi } 981*7fd79137SRobert Mustacchi 982*7fd79137SRobert Mustacchi return (ctf_diff_type(cds, ifp, iid, ofp, oid)); 983*7fd79137SRobert Mustacchi } 984*7fd79137SRobert Mustacchi 985*7fd79137SRobert Mustacchi /* ARGSUSED */ 986*7fd79137SRobert Mustacchi static void 987*7fd79137SRobert Mustacchi ctf_diff_void_cb(ctf_file_t *ifp, ctf_id_t iid, boolean_t same, ctf_file_t *ofp, 988*7fd79137SRobert Mustacchi ctf_id_t oid, void *arg) 989*7fd79137SRobert Mustacchi { 990*7fd79137SRobert Mustacchi } 991*7fd79137SRobert Mustacchi 992*7fd79137SRobert Mustacchi /* ARGSUSED */ 993*7fd79137SRobert Mustacchi static int 994*7fd79137SRobert Mustacchi ctf_diff_func_count(const char *name, ulong_t symidx, ctf_funcinfo_t *fip, 995*7fd79137SRobert Mustacchi void *arg) 996*7fd79137SRobert Mustacchi { 997*7fd79137SRobert Mustacchi uint32_t *ip = arg; 998*7fd79137SRobert Mustacchi 999*7fd79137SRobert Mustacchi *ip = *ip + 1; 1000*7fd79137SRobert Mustacchi return (0); 1001*7fd79137SRobert Mustacchi } 1002*7fd79137SRobert Mustacchi 1003*7fd79137SRobert Mustacchi /* ARGSUSED */ 1004*7fd79137SRobert Mustacchi static int 1005*7fd79137SRobert Mustacchi ctf_diff_func_fill_cb(const char *name, ulong_t symidx, ctf_funcinfo_t *fip, 1006*7fd79137SRobert Mustacchi void *arg) 1007*7fd79137SRobert Mustacchi { 1008*7fd79137SRobert Mustacchi uint_t *next, max; 1009*7fd79137SRobert Mustacchi ctf_diff_func_t *funcptr; 1010*7fd79137SRobert Mustacchi ctf_diff_t *cds = arg; 1011*7fd79137SRobert Mustacchi 1012*7fd79137SRobert Mustacchi if (cds->cds_ffillip == B_TRUE) { 1013*7fd79137SRobert Mustacchi max = cds->cds_nifuncs; 1014*7fd79137SRobert Mustacchi next = &cds->cds_nextifunc; 1015*7fd79137SRobert Mustacchi funcptr = cds->cds_ifuncs + *next; 1016*7fd79137SRobert Mustacchi } else { 1017*7fd79137SRobert Mustacchi max = cds->cds_nofuncs; 1018*7fd79137SRobert Mustacchi next = &cds->cds_nextofunc; 1019*7fd79137SRobert Mustacchi funcptr = cds->cds_ofuncs + *next; 1020*7fd79137SRobert Mustacchi 1021*7fd79137SRobert Mustacchi } 1022*7fd79137SRobert Mustacchi 1023*7fd79137SRobert Mustacchi VERIFY(*next < max); 1024*7fd79137SRobert Mustacchi funcptr->cdf_name = name; 1025*7fd79137SRobert Mustacchi funcptr->cdf_symidx = symidx; 1026*7fd79137SRobert Mustacchi funcptr->cdf_matchidx = ULONG_MAX; 1027*7fd79137SRobert Mustacchi *next = *next + 1; 1028*7fd79137SRobert Mustacchi 1029*7fd79137SRobert Mustacchi return (0); 1030*7fd79137SRobert Mustacchi } 1031*7fd79137SRobert Mustacchi 1032*7fd79137SRobert Mustacchi int 1033*7fd79137SRobert Mustacchi ctf_diff_func_fill(ctf_diff_t *cds) 1034*7fd79137SRobert Mustacchi { 1035*7fd79137SRobert Mustacchi int ret; 1036*7fd79137SRobert Mustacchi uint32_t ifcount, ofcount, idcnt, cti; 1037*7fd79137SRobert Mustacchi ulong_t i, j; 1038*7fd79137SRobert Mustacchi ctf_id_t *iids, *oids; 1039*7fd79137SRobert Mustacchi 1040*7fd79137SRobert Mustacchi ifcount = 0; 1041*7fd79137SRobert Mustacchi ofcount = 0; 1042*7fd79137SRobert Mustacchi idcnt = 0; 1043*7fd79137SRobert Mustacchi iids = NULL; 1044*7fd79137SRobert Mustacchi oids = NULL; 1045*7fd79137SRobert Mustacchi 1046*7fd79137SRobert Mustacchi ret = ctf_function_iter(cds->cds_ifp, ctf_diff_func_count, &ifcount); 1047*7fd79137SRobert Mustacchi if (ret != 0) 1048*7fd79137SRobert Mustacchi return (ret); 1049*7fd79137SRobert Mustacchi ret = ctf_function_iter(cds->cds_ofp, ctf_diff_func_count, &ofcount); 1050*7fd79137SRobert Mustacchi if (ret != 0) 1051*7fd79137SRobert Mustacchi return (ret); 1052*7fd79137SRobert Mustacchi 1053*7fd79137SRobert Mustacchi cds->cds_ifuncs = ctf_alloc(sizeof (ctf_diff_func_t) * ifcount); 1054*7fd79137SRobert Mustacchi if (cds->cds_ifuncs == NULL) 1055*7fd79137SRobert Mustacchi return (ctf_set_errno(cds->cds_ifp, ENOMEM)); 1056*7fd79137SRobert Mustacchi 1057*7fd79137SRobert Mustacchi cds->cds_nifuncs = ifcount; 1058*7fd79137SRobert Mustacchi cds->cds_nextifunc = 0; 1059*7fd79137SRobert Mustacchi 1060*7fd79137SRobert Mustacchi cds->cds_ofuncs = ctf_alloc(sizeof (ctf_diff_func_t) * ofcount); 1061*7fd79137SRobert Mustacchi if (cds->cds_ofuncs == NULL) 1062*7fd79137SRobert Mustacchi return (ctf_set_errno(cds->cds_ifp, ENOMEM)); 1063*7fd79137SRobert Mustacchi 1064*7fd79137SRobert Mustacchi cds->cds_nofuncs = ofcount; 1065*7fd79137SRobert Mustacchi cds->cds_nextofunc = 0; 1066*7fd79137SRobert Mustacchi 1067*7fd79137SRobert Mustacchi cds->cds_ffillip = B_TRUE; 1068*7fd79137SRobert Mustacchi if ((ret = ctf_function_iter(cds->cds_ifp, ctf_diff_func_fill_cb, 1069*7fd79137SRobert Mustacchi cds)) != 0) 1070*7fd79137SRobert Mustacchi return (ret); 1071*7fd79137SRobert Mustacchi 1072*7fd79137SRobert Mustacchi cds->cds_ffillip = B_FALSE; 1073*7fd79137SRobert Mustacchi if ((ret = ctf_function_iter(cds->cds_ofp, ctf_diff_func_fill_cb, 1074*7fd79137SRobert Mustacchi cds)) != 0) 1075*7fd79137SRobert Mustacchi return (ret); 1076*7fd79137SRobert Mustacchi 1077*7fd79137SRobert Mustacchi /* 1078*7fd79137SRobert Mustacchi * Everything is initialized to not match. This could probably be faster 1079*7fd79137SRobert Mustacchi * with something that used a hash. But this part of the diff isn't used 1080*7fd79137SRobert Mustacchi * by merge. 1081*7fd79137SRobert Mustacchi */ 1082*7fd79137SRobert Mustacchi for (i = 0; i < cds->cds_nifuncs; i++) { 1083*7fd79137SRobert Mustacchi for (j = 0; j < cds->cds_nofuncs; j++) { 1084*7fd79137SRobert Mustacchi ctf_diff_func_t *ifd, *ofd; 1085*7fd79137SRobert Mustacchi ctf_funcinfo_t ifip, ofip; 1086*7fd79137SRobert Mustacchi boolean_t match; 1087*7fd79137SRobert Mustacchi 1088*7fd79137SRobert Mustacchi ifd = &cds->cds_ifuncs[i]; 1089*7fd79137SRobert Mustacchi ofd = &cds->cds_ofuncs[j]; 1090*7fd79137SRobert Mustacchi if (strcmp(ifd->cdf_name, ofd->cdf_name) != 0) 1091*7fd79137SRobert Mustacchi continue; 1092*7fd79137SRobert Mustacchi 1093*7fd79137SRobert Mustacchi ret = ctf_func_info(cds->cds_ifp, ifd->cdf_symidx, 1094*7fd79137SRobert Mustacchi &ifip); 1095*7fd79137SRobert Mustacchi if (ret != 0) 1096*7fd79137SRobert Mustacchi goto out; 1097*7fd79137SRobert Mustacchi ret = ctf_func_info(cds->cds_ofp, ofd->cdf_symidx, 1098*7fd79137SRobert Mustacchi &ofip); 1099*7fd79137SRobert Mustacchi if (ret != 0) { 1100*7fd79137SRobert Mustacchi ret = ctf_set_errno(cds->cds_ifp, 1101*7fd79137SRobert Mustacchi ctf_errno(cds->cds_ofp)); 1102*7fd79137SRobert Mustacchi goto out; 1103*7fd79137SRobert Mustacchi } 1104*7fd79137SRobert Mustacchi 1105*7fd79137SRobert Mustacchi if (ifip.ctc_argc != ofip.ctc_argc && 1106*7fd79137SRobert Mustacchi ifip.ctc_flags != ofip.ctc_flags) 1107*7fd79137SRobert Mustacchi continue; 1108*7fd79137SRobert Mustacchi 1109*7fd79137SRobert Mustacchi /* Validate return type and arguments are the same */ 1110*7fd79137SRobert Mustacchi if (ctf_diff_symid(cds, ifip.ctc_return, 1111*7fd79137SRobert Mustacchi ofip.ctc_return)) 1112*7fd79137SRobert Mustacchi continue; 1113*7fd79137SRobert Mustacchi 1114*7fd79137SRobert Mustacchi if (ifip.ctc_argc > idcnt) { 1115*7fd79137SRobert Mustacchi if (iids != NULL) 1116*7fd79137SRobert Mustacchi ctf_free(iids, 1117*7fd79137SRobert Mustacchi sizeof (ctf_id_t) * idcnt); 1118*7fd79137SRobert Mustacchi if (oids != NULL) 1119*7fd79137SRobert Mustacchi ctf_free(oids, 1120*7fd79137SRobert Mustacchi sizeof (ctf_id_t) * idcnt); 1121*7fd79137SRobert Mustacchi iids = oids = NULL; 1122*7fd79137SRobert Mustacchi idcnt = ifip.ctc_argc; 1123*7fd79137SRobert Mustacchi iids = ctf_alloc(sizeof (ctf_id_t) * idcnt); 1124*7fd79137SRobert Mustacchi if (iids == NULL) { 1125*7fd79137SRobert Mustacchi ret = ctf_set_errno(cds->cds_ifp, 1126*7fd79137SRobert Mustacchi ENOMEM); 1127*7fd79137SRobert Mustacchi goto out; 1128*7fd79137SRobert Mustacchi } 1129*7fd79137SRobert Mustacchi oids = ctf_alloc(sizeof (ctf_id_t) * idcnt); 1130*7fd79137SRobert Mustacchi if (iids == NULL) { 1131*7fd79137SRobert Mustacchi ret = ctf_set_errno(cds->cds_ifp, 1132*7fd79137SRobert Mustacchi ENOMEM); 1133*7fd79137SRobert Mustacchi goto out; 1134*7fd79137SRobert Mustacchi } 1135*7fd79137SRobert Mustacchi } 1136*7fd79137SRobert Mustacchi 1137*7fd79137SRobert Mustacchi if ((ret = ctf_func_args(cds->cds_ifp, ifd->cdf_symidx, 1138*7fd79137SRobert Mustacchi ifip.ctc_argc, iids)) != 0) 1139*7fd79137SRobert Mustacchi goto out; 1140*7fd79137SRobert Mustacchi if ((ret = ctf_func_args(cds->cds_ofp, ofd->cdf_symidx, 1141*7fd79137SRobert Mustacchi ofip.ctc_argc, oids)) != 0) 1142*7fd79137SRobert Mustacchi goto out; 1143*7fd79137SRobert Mustacchi 1144*7fd79137SRobert Mustacchi match = B_TRUE; 1145*7fd79137SRobert Mustacchi for (cti = 0; cti < ifip.ctc_argc; cti++) { 1146*7fd79137SRobert Mustacchi if (ctf_diff_symid(cds, iids[cti], oids[cti])) { 1147*7fd79137SRobert Mustacchi match = B_FALSE; 1148*7fd79137SRobert Mustacchi break; 1149*7fd79137SRobert Mustacchi } 1150*7fd79137SRobert Mustacchi } 1151*7fd79137SRobert Mustacchi 1152*7fd79137SRobert Mustacchi if (match == B_FALSE) 1153*7fd79137SRobert Mustacchi continue; 1154*7fd79137SRobert Mustacchi 1155*7fd79137SRobert Mustacchi ifd->cdf_matchidx = j; 1156*7fd79137SRobert Mustacchi ofd->cdf_matchidx = i; 1157*7fd79137SRobert Mustacchi break; 1158*7fd79137SRobert Mustacchi } 1159*7fd79137SRobert Mustacchi } 1160*7fd79137SRobert Mustacchi 1161*7fd79137SRobert Mustacchi ret = 0; 1162*7fd79137SRobert Mustacchi 1163*7fd79137SRobert Mustacchi out: 1164*7fd79137SRobert Mustacchi if (iids != NULL) 1165*7fd79137SRobert Mustacchi ctf_free(iids, sizeof (ctf_id_t) * idcnt); 1166*7fd79137SRobert Mustacchi if (oids != NULL) 1167*7fd79137SRobert Mustacchi ctf_free(oids, sizeof (ctf_id_t) * idcnt); 1168*7fd79137SRobert Mustacchi 1169*7fd79137SRobert Mustacchi return (ret); 1170*7fd79137SRobert Mustacchi } 1171*7fd79137SRobert Mustacchi 1172*7fd79137SRobert Mustacchi /* 1173*7fd79137SRobert Mustacchi * In general, two functions are the same, if they have the same name and their 1174*7fd79137SRobert Mustacchi * arguments have the same types, including the return type. Like types, we 1175*7fd79137SRobert Mustacchi * basically have to do this in two passes. In the first phase we walk every 1176*7fd79137SRobert Mustacchi * type in the first container and try to find a match in the second. 1177*7fd79137SRobert Mustacchi */ 1178*7fd79137SRobert Mustacchi int 1179*7fd79137SRobert Mustacchi ctf_diff_functions(ctf_diff_t *cds, ctf_diff_func_f cb, void *arg) 1180*7fd79137SRobert Mustacchi { 1181*7fd79137SRobert Mustacchi int ret; 1182*7fd79137SRobert Mustacchi ulong_t i; 1183*7fd79137SRobert Mustacchi 1184*7fd79137SRobert Mustacchi if (cds->cds_tvalid == B_FALSE) { 1185*7fd79137SRobert Mustacchi if ((ret = ctf_diff_types(cds, ctf_diff_void_cb, NULL)) != 0) 1186*7fd79137SRobert Mustacchi return (ret); 1187*7fd79137SRobert Mustacchi } 1188*7fd79137SRobert Mustacchi 1189*7fd79137SRobert Mustacchi if (cds->cds_fvalid == B_FALSE) { 1190*7fd79137SRobert Mustacchi if ((ret = ctf_diff_func_fill(cds)) != 0) 1191*7fd79137SRobert Mustacchi return (ret); 1192*7fd79137SRobert Mustacchi cds->cds_fvalid = B_TRUE; 1193*7fd79137SRobert Mustacchi } 1194*7fd79137SRobert Mustacchi 1195*7fd79137SRobert Mustacchi for (i = 0; i < cds->cds_nifuncs; i++) { 1196*7fd79137SRobert Mustacchi if (cds->cds_ifuncs[i].cdf_matchidx == ULONG_MAX) { 1197*7fd79137SRobert Mustacchi cb(cds->cds_ifp, cds->cds_ifuncs[i].cdf_symidx, 1198*7fd79137SRobert Mustacchi B_FALSE, NULL, ULONG_MAX, arg); 1199*7fd79137SRobert Mustacchi } else { 1200*7fd79137SRobert Mustacchi ulong_t idx = cds->cds_ifuncs[i].cdf_matchidx; 1201*7fd79137SRobert Mustacchi cb(cds->cds_ifp, cds->cds_ifuncs[i].cdf_symidx, B_TRUE, 1202*7fd79137SRobert Mustacchi cds->cds_ofp, cds->cds_ofuncs[idx].cdf_symidx, arg); 1203*7fd79137SRobert Mustacchi } 1204*7fd79137SRobert Mustacchi } 1205*7fd79137SRobert Mustacchi 1206*7fd79137SRobert Mustacchi for (i = 0; i < cds->cds_nofuncs; i++) { 1207*7fd79137SRobert Mustacchi if (cds->cds_ofuncs[i].cdf_matchidx != ULONG_MAX) 1208*7fd79137SRobert Mustacchi continue; 1209*7fd79137SRobert Mustacchi cb(cds->cds_ofp, cds->cds_ofuncs[i].cdf_symidx, B_FALSE, 1210*7fd79137SRobert Mustacchi NULL, ULONG_MAX, arg); 1211*7fd79137SRobert Mustacchi } 1212*7fd79137SRobert Mustacchi 1213*7fd79137SRobert Mustacchi return (0); 1214*7fd79137SRobert Mustacchi } 1215*7fd79137SRobert Mustacchi 1216*7fd79137SRobert Mustacchi static int 1217*7fd79137SRobert Mustacchi ctf_diff_obj_fill_cb(const char *name, ctf_id_t id, ulong_t symidx, void *arg) 1218*7fd79137SRobert Mustacchi { 1219*7fd79137SRobert Mustacchi uint_t *next, max; 1220*7fd79137SRobert Mustacchi ctf_diff_obj_t *objptr; 1221*7fd79137SRobert Mustacchi ctf_diff_t *cds = arg; 1222*7fd79137SRobert Mustacchi 1223*7fd79137SRobert Mustacchi if (cds->cds_ofillip == B_TRUE) { 1224*7fd79137SRobert Mustacchi max = cds->cds_niobj; 1225*7fd79137SRobert Mustacchi next = &cds->cds_nextiobj; 1226*7fd79137SRobert Mustacchi objptr = cds->cds_iobj + *next; 1227*7fd79137SRobert Mustacchi } else { 1228*7fd79137SRobert Mustacchi max = cds->cds_noobj; 1229*7fd79137SRobert Mustacchi next = &cds->cds_nextoobj; 1230*7fd79137SRobert Mustacchi objptr = cds->cds_oobj+ *next; 1231*7fd79137SRobert Mustacchi 1232*7fd79137SRobert Mustacchi } 1233*7fd79137SRobert Mustacchi 1234*7fd79137SRobert Mustacchi VERIFY(*next < max); 1235*7fd79137SRobert Mustacchi objptr->cdo_name = name; 1236*7fd79137SRobert Mustacchi objptr->cdo_symidx = symidx; 1237*7fd79137SRobert Mustacchi objptr->cdo_id = id; 1238*7fd79137SRobert Mustacchi objptr->cdo_matchidx = ULONG_MAX; 1239*7fd79137SRobert Mustacchi *next = *next + 1; 1240*7fd79137SRobert Mustacchi 1241*7fd79137SRobert Mustacchi return (0); 1242*7fd79137SRobert Mustacchi } 1243*7fd79137SRobert Mustacchi 1244*7fd79137SRobert Mustacchi /* ARGSUSED */ 1245*7fd79137SRobert Mustacchi static int 1246*7fd79137SRobert Mustacchi ctf_diff_obj_count(const char *name, ctf_id_t id, ulong_t symidx, void *arg) 1247*7fd79137SRobert Mustacchi { 1248*7fd79137SRobert Mustacchi uint32_t *count = arg; 1249*7fd79137SRobert Mustacchi 1250*7fd79137SRobert Mustacchi *count = *count + 1; 1251*7fd79137SRobert Mustacchi 1252*7fd79137SRobert Mustacchi return (0); 1253*7fd79137SRobert Mustacchi } 1254*7fd79137SRobert Mustacchi 1255*7fd79137SRobert Mustacchi 1256*7fd79137SRobert Mustacchi static int 1257*7fd79137SRobert Mustacchi ctf_diff_obj_fill(ctf_diff_t *cds) 1258*7fd79137SRobert Mustacchi { 1259*7fd79137SRobert Mustacchi int ret; 1260*7fd79137SRobert Mustacchi uint32_t iocount, oocount; 1261*7fd79137SRobert Mustacchi ulong_t i, j; 1262*7fd79137SRobert Mustacchi 1263*7fd79137SRobert Mustacchi iocount = 0; 1264*7fd79137SRobert Mustacchi oocount = 0; 1265*7fd79137SRobert Mustacchi 1266*7fd79137SRobert Mustacchi ret = ctf_object_iter(cds->cds_ifp, ctf_diff_obj_count, &iocount); 1267*7fd79137SRobert Mustacchi if (ret != 0) 1268*7fd79137SRobert Mustacchi return (ret); 1269*7fd79137SRobert Mustacchi 1270*7fd79137SRobert Mustacchi ret = ctf_object_iter(cds->cds_ofp, ctf_diff_obj_count, &oocount); 1271*7fd79137SRobert Mustacchi if (ret != 0) 1272*7fd79137SRobert Mustacchi return (ret); 1273*7fd79137SRobert Mustacchi 1274*7fd79137SRobert Mustacchi cds->cds_iobj = ctf_alloc(sizeof (ctf_diff_obj_t) * iocount); 1275*7fd79137SRobert Mustacchi if (cds->cds_iobj == NULL) 1276*7fd79137SRobert Mustacchi return (ctf_set_errno(cds->cds_ifp, ENOMEM)); 1277*7fd79137SRobert Mustacchi cds->cds_niobj = iocount; 1278*7fd79137SRobert Mustacchi cds->cds_nextiobj = 0; 1279*7fd79137SRobert Mustacchi 1280*7fd79137SRobert Mustacchi cds->cds_oobj = ctf_alloc(sizeof (ctf_diff_obj_t) * oocount); 1281*7fd79137SRobert Mustacchi if (cds->cds_oobj == NULL) 1282*7fd79137SRobert Mustacchi return (ctf_set_errno(cds->cds_ifp, ENOMEM)); 1283*7fd79137SRobert Mustacchi cds->cds_noobj = oocount; 1284*7fd79137SRobert Mustacchi cds->cds_nextoobj = 0; 1285*7fd79137SRobert Mustacchi 1286*7fd79137SRobert Mustacchi cds->cds_ofillip = B_TRUE; 1287*7fd79137SRobert Mustacchi if ((ret = ctf_object_iter(cds->cds_ifp, ctf_diff_obj_fill_cb, 1288*7fd79137SRobert Mustacchi cds)) != 0) 1289*7fd79137SRobert Mustacchi return (ret); 1290*7fd79137SRobert Mustacchi 1291*7fd79137SRobert Mustacchi cds->cds_ofillip = B_FALSE; 1292*7fd79137SRobert Mustacchi if ((ret = ctf_object_iter(cds->cds_ofp, ctf_diff_obj_fill_cb, 1293*7fd79137SRobert Mustacchi cds)) != 0) 1294*7fd79137SRobert Mustacchi return (ret); 1295*7fd79137SRobert Mustacchi 1296*7fd79137SRobert Mustacchi for (i = 0; i < cds->cds_niobj; i++) { 1297*7fd79137SRobert Mustacchi for (j = 0; j < cds->cds_noobj; j++) { 1298*7fd79137SRobert Mustacchi ctf_diff_obj_t *id, *od; 1299*7fd79137SRobert Mustacchi 1300*7fd79137SRobert Mustacchi id = &cds->cds_iobj[i]; 1301*7fd79137SRobert Mustacchi od = &cds->cds_oobj[j]; 1302*7fd79137SRobert Mustacchi 1303*7fd79137SRobert Mustacchi if (id->cdo_name == NULL || od->cdo_name == NULL) 1304*7fd79137SRobert Mustacchi continue; 1305*7fd79137SRobert Mustacchi if (strcmp(id->cdo_name, od->cdo_name) != 0) 1306*7fd79137SRobert Mustacchi continue; 1307*7fd79137SRobert Mustacchi 1308*7fd79137SRobert Mustacchi if (ctf_diff_symid(cds, id->cdo_id, od->cdo_id)) { 1309*7fd79137SRobert Mustacchi continue; 1310*7fd79137SRobert Mustacchi } 1311*7fd79137SRobert Mustacchi 1312*7fd79137SRobert Mustacchi id->cdo_matchidx = j; 1313*7fd79137SRobert Mustacchi od->cdo_matchidx = i; 1314*7fd79137SRobert Mustacchi break; 1315*7fd79137SRobert Mustacchi } 1316*7fd79137SRobert Mustacchi } 1317*7fd79137SRobert Mustacchi 1318*7fd79137SRobert Mustacchi return (0); 1319*7fd79137SRobert Mustacchi } 1320*7fd79137SRobert Mustacchi 1321*7fd79137SRobert Mustacchi int 1322*7fd79137SRobert Mustacchi ctf_diff_objects(ctf_diff_t *cds, ctf_diff_obj_f cb, void *arg) 1323*7fd79137SRobert Mustacchi { 1324*7fd79137SRobert Mustacchi int ret; 1325*7fd79137SRobert Mustacchi ulong_t i; 1326*7fd79137SRobert Mustacchi 1327*7fd79137SRobert Mustacchi if (cds->cds_tvalid == B_FALSE) { 1328*7fd79137SRobert Mustacchi if ((ret = ctf_diff_types(cds, ctf_diff_void_cb, NULL)) != 0) 1329*7fd79137SRobert Mustacchi return (ret); 1330*7fd79137SRobert Mustacchi } 1331*7fd79137SRobert Mustacchi 1332*7fd79137SRobert Mustacchi if (cds->cds_ovalid == B_FALSE) { 1333*7fd79137SRobert Mustacchi if ((ret = ctf_diff_obj_fill(cds)) != 0) 1334*7fd79137SRobert Mustacchi return (ret); 1335*7fd79137SRobert Mustacchi cds->cds_ovalid = B_TRUE; 1336*7fd79137SRobert Mustacchi } 1337*7fd79137SRobert Mustacchi 1338*7fd79137SRobert Mustacchi for (i = 0; i < cds->cds_niobj; i++) { 1339*7fd79137SRobert Mustacchi ctf_diff_obj_t *o = &cds->cds_iobj[i]; 1340*7fd79137SRobert Mustacchi 1341*7fd79137SRobert Mustacchi if (cds->cds_iobj[i].cdo_matchidx == ULONG_MAX) { 1342*7fd79137SRobert Mustacchi cb(cds->cds_ifp, o->cdo_symidx, o->cdo_id, B_FALSE, 1343*7fd79137SRobert Mustacchi NULL, ULONG_MAX, CTF_ERR, arg); 1344*7fd79137SRobert Mustacchi } else { 1345*7fd79137SRobert Mustacchi ctf_diff_obj_t *alt = &cds->cds_oobj[o->cdo_matchidx]; 1346*7fd79137SRobert Mustacchi cb(cds->cds_ifp, o->cdo_symidx, o->cdo_id, B_TRUE, 1347*7fd79137SRobert Mustacchi cds->cds_ofp, alt->cdo_symidx, alt->cdo_id, arg); 1348*7fd79137SRobert Mustacchi } 1349*7fd79137SRobert Mustacchi } 1350*7fd79137SRobert Mustacchi 1351*7fd79137SRobert Mustacchi for (i = 0; i < cds->cds_noobj; i++) { 1352*7fd79137SRobert Mustacchi ctf_diff_obj_t *o = &cds->cds_oobj[i]; 1353*7fd79137SRobert Mustacchi if (o->cdo_matchidx != ULONG_MAX) 1354*7fd79137SRobert Mustacchi continue; 1355*7fd79137SRobert Mustacchi cb(cds->cds_ofp, o->cdo_symidx, o->cdo_id, B_FALSE, NULL, 1356*7fd79137SRobert Mustacchi ULONG_MAX, CTF_ERR, arg); 1357*7fd79137SRobert Mustacchi } 1358*7fd79137SRobert Mustacchi 1359*7fd79137SRobert Mustacchi return (0); 1360*7fd79137SRobert Mustacchi } 1361