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
ctf_diff_name(ctf_file_t * ifp,ctf_id_t iid,ctf_file_t * ofp,ctf_id_t oid)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
ctf_diff_number(ctf_file_t * ifp,ctf_id_t iid,ctf_file_t * ofp,ctf_id_t oid)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
ctf_diff_typedef(ctf_diff_t * cds,ctf_file_t * ifp,ctf_id_t iid,ctf_file_t * ofp,ctf_id_t oid)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
ctf_diff_qualifier(ctf_diff_t * cds,ctf_file_t * ifp,ctf_id_t iid,ctf_file_t * ofp,ctf_id_t oid)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
ctf_diff_array(ctf_diff_t * cds,ctf_file_t * ifp,ctf_id_t iid,ctf_file_t * ofp,ctf_id_t oid)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
ctf_diff_fptr(ctf_diff_t * cds,ctf_file_t * ifp,ctf_id_t iid,ctf_file_t * ofp,ctf_id_t oid)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
ctf_diff_struct(ctf_diff_t * cds,ctf_file_t * ifp,ctf_id_t iid,ctf_file_t * ofp,ctf_id_t oid)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
ctf_diff_union_check_member(const char * name,ctf_id_t id,ulong_t off,void * arg)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
ctf_diff_union_check_fp(const char * name,ctf_id_t id,ulong_t off,void * arg)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
ctf_diff_union(ctf_diff_t * cds,ctf_file_t * ifp,ctf_id_t iid,ctf_file_t * ofp,ctf_id_t oid)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
ctf_diff_enum(ctf_file_t * ifp,ctf_id_t iid,ctf_file_t * ofp,ctf_id_t oid)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
ctf_diff_forward(ctf_file_t * ifp,ctf_id_t iid,ctf_file_t * ofp,ctf_id_t oid)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
ctf_diff_type(ctf_diff_t * cds,ctf_file_t * ifp,ctf_id_t iid,ctf_file_t * ofp,ctf_id_t oid)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
ctf_diff_pass1(ctf_diff_t * cds,boolean_t self)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
ctf_diff_pass2(ctf_diff_t * cds)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
ctf_diff_init(ctf_file_t * ifp,ctf_file_t * ofp,ctf_diff_t ** cdsp)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
ctf_diff_types(ctf_diff_t * cds,ctf_diff_type_f cb,void * arg)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
ctf_diff_self(ctf_diff_t * cds,ctf_diff_type_f cb,void * arg)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
ctf_diff_fini(ctf_diff_t * cds)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
ctf_diff_getflags(ctf_diff_t * cds)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
ctf_diff_setflags(ctf_diff_t * cds,uint_t flags)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
ctf_diff_symid(ctf_diff_t * cds,ctf_id_t iid,ctf_id_t oid)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
ctf_diff_void_cb(ctf_file_t * ifp,ctf_id_t iid,boolean_t same,ctf_file_t * ofp,ctf_id_t oid,void * arg)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
ctf_diff_func_count(const char * name,ulong_t symidx,ctf_funcinfo_t * fip,void * arg)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
ctf_diff_func_fill_cb(const char * name,ulong_t symidx,ctf_funcinfo_t * fip,void * arg)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
ctf_diff_func_fill(ctf_diff_t * cds)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
ctf_diff_functions(ctf_diff_t * cds,ctf_diff_func_f cb,void * arg)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
ctf_diff_obj_fill_cb(const char * name,ctf_id_t id,ulong_t symidx,void * arg)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
ctf_diff_obj_count(const char * name,ctf_id_t id,ulong_t symidx,void * arg)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
ctf_diff_obj_fill(ctf_diff_t * cds)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
ctf_diff_objects(ctf_diff_t * cds,ctf_diff_obj_f cb,void * arg)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