1*f3e7f55eSRobert Mustacchi /*
2*f3e7f55eSRobert Mustacchi * This file and its contents are supplied under the terms of the
3*f3e7f55eSRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
4*f3e7f55eSRobert Mustacchi * You may only use this file in accordance with the terms of version
5*f3e7f55eSRobert Mustacchi * 1.0 of the CDDL.
6*f3e7f55eSRobert Mustacchi *
7*f3e7f55eSRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
8*f3e7f55eSRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
9*f3e7f55eSRobert Mustacchi * http://www.illumos.org/license/CDDL.
10*f3e7f55eSRobert Mustacchi */
11*f3e7f55eSRobert Mustacchi
12*f3e7f55eSRobert Mustacchi /*
13*f3e7f55eSRobert Mustacchi * Copyright (c) 2015, Joyent, Inc.
14*f3e7f55eSRobert Mustacchi */
15*f3e7f55eSRobert Mustacchi
16*f3e7f55eSRobert Mustacchi /*
17*f3e7f55eSRobert Mustacchi * diff two CTF containers
18*f3e7f55eSRobert Mustacchi */
19*f3e7f55eSRobert Mustacchi
20*f3e7f55eSRobert Mustacchi #include <stdio.h>
21*f3e7f55eSRobert Mustacchi #include <stdlib.h>
22*f3e7f55eSRobert Mustacchi #include <errno.h>
23*f3e7f55eSRobert Mustacchi #include <strings.h>
24*f3e7f55eSRobert Mustacchi #include <libctf.h>
25*f3e7f55eSRobert Mustacchi #include <libgen.h>
26*f3e7f55eSRobert Mustacchi #include <stdarg.h>
27*f3e7f55eSRobert Mustacchi
28*f3e7f55eSRobert Mustacchi #define CTFDIFF_NAMELEN 256
29*f3e7f55eSRobert Mustacchi
30*f3e7f55eSRobert Mustacchi #define CTFDIFF_EXIT_SIMILAR 0
31*f3e7f55eSRobert Mustacchi #define CTFDIFF_EXIT_DIFFERENT 1
32*f3e7f55eSRobert Mustacchi #define CTFDIFF_EXIT_USAGE 2
33*f3e7f55eSRobert Mustacchi #define CTFDIFF_EXIT_ERROR 3
34*f3e7f55eSRobert Mustacchi
35*f3e7f55eSRobert Mustacchi typedef enum ctf_diff_cmd {
36*f3e7f55eSRobert Mustacchi CTF_DIFF_TYPES = 0x01,
37*f3e7f55eSRobert Mustacchi CTF_DIFF_FUNCS = 0x02,
38*f3e7f55eSRobert Mustacchi CTF_DIFF_OBJS = 0x04,
39*f3e7f55eSRobert Mustacchi CTF_DIFF_DEFAULT = 0x07,
40*f3e7f55eSRobert Mustacchi CTF_DIFF_LABEL = 0x08,
41*f3e7f55eSRobert Mustacchi CTF_DIFF_ALL = 0x0f
42*f3e7f55eSRobert Mustacchi } ctf_diff_cmd_t;
43*f3e7f55eSRobert Mustacchi
44*f3e7f55eSRobert Mustacchi typedef struct {
45*f3e7f55eSRobert Mustacchi int dil_next;
46*f3e7f55eSRobert Mustacchi const char **dil_labels;
47*f3e7f55eSRobert Mustacchi } ctfdiff_label_t;
48*f3e7f55eSRobert Mustacchi
49*f3e7f55eSRobert Mustacchi static char *g_progname;
50*f3e7f55eSRobert Mustacchi static const char *g_iname;
51*f3e7f55eSRobert Mustacchi static ctf_file_t *g_ifp;
52*f3e7f55eSRobert Mustacchi static const char *g_oname;
53*f3e7f55eSRobert Mustacchi static ctf_file_t *g_ofp;
54*f3e7f55eSRobert Mustacchi static char **g_typelist = NULL;
55*f3e7f55eSRobert Mustacchi static int g_nexttype = 0;
56*f3e7f55eSRobert Mustacchi static int g_ntypes = 0;
57*f3e7f55eSRobert Mustacchi static char **g_objlist = NULL;
58*f3e7f55eSRobert Mustacchi static int g_nextfunc = 0;
59*f3e7f55eSRobert Mustacchi static int g_nfuncs = 0;
60*f3e7f55eSRobert Mustacchi static char **g_funclist = NULL;
61*f3e7f55eSRobert Mustacchi static int g_nextobj = 0;
62*f3e7f55eSRobert Mustacchi static int g_nobjs = 0;
63*f3e7f55eSRobert Mustacchi static boolean_t g_onlydiff = B_FALSE;
64*f3e7f55eSRobert Mustacchi static boolean_t g_different = B_FALSE;
65*f3e7f55eSRobert Mustacchi static ctf_diff_cmd_t g_flag = 0;
66*f3e7f55eSRobert Mustacchi
67*f3e7f55eSRobert Mustacchi static void
ctfdiff_fatal(const char * fmt,...)68*f3e7f55eSRobert Mustacchi ctfdiff_fatal(const char *fmt, ...)
69*f3e7f55eSRobert Mustacchi {
70*f3e7f55eSRobert Mustacchi va_list ap;
71*f3e7f55eSRobert Mustacchi
72*f3e7f55eSRobert Mustacchi (void) fprintf(stderr, "%s: ", g_progname);
73*f3e7f55eSRobert Mustacchi va_start(ap, fmt);
74*f3e7f55eSRobert Mustacchi (void) vfprintf(stderr, fmt, ap);
75*f3e7f55eSRobert Mustacchi va_end(ap);
76*f3e7f55eSRobert Mustacchi
77*f3e7f55eSRobert Mustacchi exit(CTFDIFF_EXIT_ERROR);
78*f3e7f55eSRobert Mustacchi }
79*f3e7f55eSRobert Mustacchi
80*f3e7f55eSRobert Mustacchi static const char *
ctfdiff_fp_to_name(ctf_file_t * fp)81*f3e7f55eSRobert Mustacchi ctfdiff_fp_to_name(ctf_file_t *fp)
82*f3e7f55eSRobert Mustacchi {
83*f3e7f55eSRobert Mustacchi if (fp == g_ifp)
84*f3e7f55eSRobert Mustacchi return (g_iname);
85*f3e7f55eSRobert Mustacchi if (fp == g_ofp)
86*f3e7f55eSRobert Mustacchi return (g_oname);
87*f3e7f55eSRobert Mustacchi return (NULL);
88*f3e7f55eSRobert Mustacchi }
89*f3e7f55eSRobert Mustacchi
90*f3e7f55eSRobert Mustacchi /* ARGSUSED */
91*f3e7f55eSRobert Mustacchi static void
ctfdiff_func_cb(ctf_file_t * ifp,ulong_t iidx,boolean_t similar,ctf_file_t * ofp,ulong_t oidx,void * arg)92*f3e7f55eSRobert Mustacchi ctfdiff_func_cb(ctf_file_t *ifp, ulong_t iidx, boolean_t similar,
93*f3e7f55eSRobert Mustacchi ctf_file_t *ofp, ulong_t oidx, void *arg)
94*f3e7f55eSRobert Mustacchi {
95*f3e7f55eSRobert Mustacchi char namebuf[CTFDIFF_NAMELEN];
96*f3e7f55eSRobert Mustacchi
97*f3e7f55eSRobert Mustacchi if (similar == B_TRUE)
98*f3e7f55eSRobert Mustacchi return;
99*f3e7f55eSRobert Mustacchi
100*f3e7f55eSRobert Mustacchi if (ctf_symbol_name(ifp, iidx, namebuf, sizeof (namebuf)) == NULL) {
101*f3e7f55eSRobert Mustacchi if (g_nextfunc != 0)
102*f3e7f55eSRobert Mustacchi return;
103*f3e7f55eSRobert Mustacchi (void) printf("ctf container %s function %lu is different\n",
104*f3e7f55eSRobert Mustacchi ctfdiff_fp_to_name(ifp), iidx);
105*f3e7f55eSRobert Mustacchi } else {
106*f3e7f55eSRobert Mustacchi if (g_nextfunc != 0) {
107*f3e7f55eSRobert Mustacchi int i;
108*f3e7f55eSRobert Mustacchi for (i = 0; i < g_nextfunc; i++) {
109*f3e7f55eSRobert Mustacchi if (strcmp(g_funclist[i], namebuf) == 0)
110*f3e7f55eSRobert Mustacchi break;
111*f3e7f55eSRobert Mustacchi }
112*f3e7f55eSRobert Mustacchi if (i == g_nextfunc)
113*f3e7f55eSRobert Mustacchi return;
114*f3e7f55eSRobert Mustacchi }
115*f3e7f55eSRobert Mustacchi (void) printf("ctf container %s function %s (%lu) is "
116*f3e7f55eSRobert Mustacchi "different\n", ctfdiff_fp_to_name(ifp), namebuf, iidx);
117*f3e7f55eSRobert Mustacchi }
118*f3e7f55eSRobert Mustacchi
119*f3e7f55eSRobert Mustacchi g_different = B_TRUE;
120*f3e7f55eSRobert Mustacchi }
121*f3e7f55eSRobert Mustacchi
122*f3e7f55eSRobert Mustacchi /* ARGSUSED */
123*f3e7f55eSRobert Mustacchi static void
ctfdiff_obj_cb(ctf_file_t * ifp,ulong_t iidx,ctf_id_t iid,boolean_t similar,ctf_file_t * ofp,ulong_t oidx,ctf_id_t oid,void * arg)124*f3e7f55eSRobert Mustacchi ctfdiff_obj_cb(ctf_file_t *ifp, ulong_t iidx, ctf_id_t iid, boolean_t similar,
125*f3e7f55eSRobert Mustacchi ctf_file_t *ofp, ulong_t oidx, ctf_id_t oid, void *arg)
126*f3e7f55eSRobert Mustacchi {
127*f3e7f55eSRobert Mustacchi char namebuf[CTFDIFF_NAMELEN];
128*f3e7f55eSRobert Mustacchi
129*f3e7f55eSRobert Mustacchi if (similar == B_TRUE)
130*f3e7f55eSRobert Mustacchi return;
131*f3e7f55eSRobert Mustacchi
132*f3e7f55eSRobert Mustacchi if (ctf_symbol_name(ifp, iidx, namebuf, sizeof (namebuf)) == NULL) {
133*f3e7f55eSRobert Mustacchi if (g_nextobj != 0)
134*f3e7f55eSRobert Mustacchi return;
135*f3e7f55eSRobert Mustacchi (void) printf("ctf container %s object %lu is different\n",
136*f3e7f55eSRobert Mustacchi ctfdiff_fp_to_name(ifp), iidx);
137*f3e7f55eSRobert Mustacchi } else {
138*f3e7f55eSRobert Mustacchi if (g_nextobj != 0) {
139*f3e7f55eSRobert Mustacchi int i;
140*f3e7f55eSRobert Mustacchi for (i = 0; i < g_nextobj; i++) {
141*f3e7f55eSRobert Mustacchi if (strcmp(g_objlist[i], namebuf) == 0)
142*f3e7f55eSRobert Mustacchi break;
143*f3e7f55eSRobert Mustacchi }
144*f3e7f55eSRobert Mustacchi if (i == g_nextobj)
145*f3e7f55eSRobert Mustacchi return;
146*f3e7f55eSRobert Mustacchi }
147*f3e7f55eSRobert Mustacchi (void) printf("ctf container %s object %s (%lu) is different\n",
148*f3e7f55eSRobert Mustacchi ctfdiff_fp_to_name(ifp), namebuf, iidx);
149*f3e7f55eSRobert Mustacchi }
150*f3e7f55eSRobert Mustacchi
151*f3e7f55eSRobert Mustacchi g_different = B_TRUE;
152*f3e7f55eSRobert Mustacchi }
153*f3e7f55eSRobert Mustacchi
154*f3e7f55eSRobert Mustacchi /* ARGSUSED */
155*f3e7f55eSRobert Mustacchi static void
ctfdiff_cb(ctf_file_t * ifp,ctf_id_t iid,boolean_t similar,ctf_file_t * ofp,ctf_id_t oid,void * arg)156*f3e7f55eSRobert Mustacchi ctfdiff_cb(ctf_file_t *ifp, ctf_id_t iid, boolean_t similar, ctf_file_t *ofp,
157*f3e7f55eSRobert Mustacchi ctf_id_t oid, void *arg)
158*f3e7f55eSRobert Mustacchi {
159*f3e7f55eSRobert Mustacchi if (similar == B_TRUE)
160*f3e7f55eSRobert Mustacchi return;
161*f3e7f55eSRobert Mustacchi
162*f3e7f55eSRobert Mustacchi if (ctf_type_kind(ifp, iid) == CTF_K_UNKNOWN)
163*f3e7f55eSRobert Mustacchi return;
164*f3e7f55eSRobert Mustacchi
165*f3e7f55eSRobert Mustacchi /*
166*f3e7f55eSRobert Mustacchi * Check if it's the type the user cares about.
167*f3e7f55eSRobert Mustacchi */
168*f3e7f55eSRobert Mustacchi if (g_nexttype != 0) {
169*f3e7f55eSRobert Mustacchi int i;
170*f3e7f55eSRobert Mustacchi char namebuf[CTFDIFF_NAMELEN];
171*f3e7f55eSRobert Mustacchi
172*f3e7f55eSRobert Mustacchi if (ctf_type_name(ifp, iid, namebuf, sizeof (namebuf)) ==
173*f3e7f55eSRobert Mustacchi NULL) {
174*f3e7f55eSRobert Mustacchi ctfdiff_fatal("failed to obtain the name "
175*f3e7f55eSRobert Mustacchi "of type %ld from %s: %s\n",
176*f3e7f55eSRobert Mustacchi iid, ctfdiff_fp_to_name(ifp),
177*f3e7f55eSRobert Mustacchi ctf_errmsg(ctf_errno(ifp)));
178*f3e7f55eSRobert Mustacchi }
179*f3e7f55eSRobert Mustacchi
180*f3e7f55eSRobert Mustacchi for (i = 0; i < g_nexttype; i++) {
181*f3e7f55eSRobert Mustacchi if (strcmp(g_typelist[i], namebuf) == 0)
182*f3e7f55eSRobert Mustacchi break;
183*f3e7f55eSRobert Mustacchi }
184*f3e7f55eSRobert Mustacchi
185*f3e7f55eSRobert Mustacchi if (i == g_nexttype)
186*f3e7f55eSRobert Mustacchi return;
187*f3e7f55eSRobert Mustacchi }
188*f3e7f55eSRobert Mustacchi
189*f3e7f55eSRobert Mustacchi g_different = B_TRUE;
190*f3e7f55eSRobert Mustacchi
191*f3e7f55eSRobert Mustacchi if (g_onlydiff == B_TRUE)
192*f3e7f55eSRobert Mustacchi return;
193*f3e7f55eSRobert Mustacchi
194*f3e7f55eSRobert Mustacchi (void) printf("ctf container %s type %ld is different\n",
195*f3e7f55eSRobert Mustacchi ctfdiff_fp_to_name(ifp), iid);
196*f3e7f55eSRobert Mustacchi }
197*f3e7f55eSRobert Mustacchi
198*f3e7f55eSRobert Mustacchi /* ARGSUSED */
199*f3e7f55eSRobert Mustacchi static int
ctfdiff_labels_count(const char * name,const ctf_lblinfo_t * li,void * arg)200*f3e7f55eSRobert Mustacchi ctfdiff_labels_count(const char *name, const ctf_lblinfo_t *li, void *arg)
201*f3e7f55eSRobert Mustacchi {
202*f3e7f55eSRobert Mustacchi uint32_t *count = arg;
203*f3e7f55eSRobert Mustacchi *count = *count + 1;
204*f3e7f55eSRobert Mustacchi
205*f3e7f55eSRobert Mustacchi return (0);
206*f3e7f55eSRobert Mustacchi }
207*f3e7f55eSRobert Mustacchi
208*f3e7f55eSRobert Mustacchi /* ARGSUSED */
209*f3e7f55eSRobert Mustacchi static int
ctfdiff_labels_fill(const char * name,const ctf_lblinfo_t * li,void * arg)210*f3e7f55eSRobert Mustacchi ctfdiff_labels_fill(const char *name, const ctf_lblinfo_t *li, void *arg)
211*f3e7f55eSRobert Mustacchi {
212*f3e7f55eSRobert Mustacchi ctfdiff_label_t *dil = arg;
213*f3e7f55eSRobert Mustacchi
214*f3e7f55eSRobert Mustacchi dil->dil_labels[dil->dil_next] = name;
215*f3e7f55eSRobert Mustacchi dil->dil_next++;
216*f3e7f55eSRobert Mustacchi
217*f3e7f55eSRobert Mustacchi return (0);
218*f3e7f55eSRobert Mustacchi }
219*f3e7f55eSRobert Mustacchi
220*f3e7f55eSRobert Mustacchi static int
ctfdiff_labels(ctf_file_t * ifp,ctf_file_t * ofp)221*f3e7f55eSRobert Mustacchi ctfdiff_labels(ctf_file_t *ifp, ctf_file_t *ofp)
222*f3e7f55eSRobert Mustacchi {
223*f3e7f55eSRobert Mustacchi int ret;
224*f3e7f55eSRobert Mustacchi uint32_t nilabel, nolabel, i, j;
225*f3e7f55eSRobert Mustacchi ctfdiff_label_t idl, odl;
226*f3e7f55eSRobert Mustacchi const char **ilptr, **olptr;
227*f3e7f55eSRobert Mustacchi
228*f3e7f55eSRobert Mustacchi nilabel = nolabel = 0;
229*f3e7f55eSRobert Mustacchi ret = ctf_label_iter(ifp, ctfdiff_labels_count, &nilabel);
230*f3e7f55eSRobert Mustacchi if (ret == CTF_ERR)
231*f3e7f55eSRobert Mustacchi return (ret);
232*f3e7f55eSRobert Mustacchi ret = ctf_label_iter(ofp, ctfdiff_labels_count, &nolabel);
233*f3e7f55eSRobert Mustacchi if (ret == CTF_ERR)
234*f3e7f55eSRobert Mustacchi return (ret);
235*f3e7f55eSRobert Mustacchi
236*f3e7f55eSRobert Mustacchi if (nilabel != nolabel) {
237*f3e7f55eSRobert Mustacchi (void) printf("ctf container %s labels differ from ctf "
238*f3e7f55eSRobert Mustacchi "container %s\n", ctfdiff_fp_to_name(ifp),
239*f3e7f55eSRobert Mustacchi ctfdiff_fp_to_name(ofp));
240*f3e7f55eSRobert Mustacchi g_different = B_TRUE;
241*f3e7f55eSRobert Mustacchi return (0);
242*f3e7f55eSRobert Mustacchi }
243*f3e7f55eSRobert Mustacchi
244*f3e7f55eSRobert Mustacchi if (nilabel == 0)
245*f3e7f55eSRobert Mustacchi return (0);
246*f3e7f55eSRobert Mustacchi
247*f3e7f55eSRobert Mustacchi ilptr = malloc(sizeof (char *) * nilabel);
248*f3e7f55eSRobert Mustacchi olptr = malloc(sizeof (char *) * nolabel);
249*f3e7f55eSRobert Mustacchi if (ilptr == NULL || olptr == NULL) {
250*f3e7f55eSRobert Mustacchi ctfdiff_fatal("failed to allocate memory for label "
251*f3e7f55eSRobert Mustacchi "comparison\n");
252*f3e7f55eSRobert Mustacchi }
253*f3e7f55eSRobert Mustacchi
254*f3e7f55eSRobert Mustacchi idl.dil_next = 0;
255*f3e7f55eSRobert Mustacchi idl.dil_labels = ilptr;
256*f3e7f55eSRobert Mustacchi odl.dil_next = 0;
257*f3e7f55eSRobert Mustacchi odl.dil_labels = olptr;
258*f3e7f55eSRobert Mustacchi
259*f3e7f55eSRobert Mustacchi if ((ret = ctf_label_iter(ifp, ctfdiff_labels_fill, &idl)) != 0)
260*f3e7f55eSRobert Mustacchi goto out;
261*f3e7f55eSRobert Mustacchi if ((ret = ctf_label_iter(ofp, ctfdiff_labels_fill, &odl)) != 0)
262*f3e7f55eSRobert Mustacchi goto out;
263*f3e7f55eSRobert Mustacchi
264*f3e7f55eSRobert Mustacchi for (i = 0; i < nilabel; i++) {
265*f3e7f55eSRobert Mustacchi for (j = 0; j < nolabel; j++) {
266*f3e7f55eSRobert Mustacchi if (strcmp(ilptr[i], olptr[j]) == 0)
267*f3e7f55eSRobert Mustacchi break;
268*f3e7f55eSRobert Mustacchi }
269*f3e7f55eSRobert Mustacchi
270*f3e7f55eSRobert Mustacchi if (j == nolabel) {
271*f3e7f55eSRobert Mustacchi (void) printf("ctf container %s labels differ from ctf "
272*f3e7f55eSRobert Mustacchi "container %s\n", ctfdiff_fp_to_name(ifp),
273*f3e7f55eSRobert Mustacchi ctfdiff_fp_to_name(ofp));
274*f3e7f55eSRobert Mustacchi g_different = B_TRUE;
275*f3e7f55eSRobert Mustacchi break;
276*f3e7f55eSRobert Mustacchi }
277*f3e7f55eSRobert Mustacchi }
278*f3e7f55eSRobert Mustacchi
279*f3e7f55eSRobert Mustacchi ret = 0;
280*f3e7f55eSRobert Mustacchi out:
281*f3e7f55eSRobert Mustacchi free(ilptr);
282*f3e7f55eSRobert Mustacchi free(olptr);
283*f3e7f55eSRobert Mustacchi return (ret);
284*f3e7f55eSRobert Mustacchi }
285*f3e7f55eSRobert Mustacchi
286*f3e7f55eSRobert Mustacchi static void
ctfdiff_usage(const char * fmt,...)287*f3e7f55eSRobert Mustacchi ctfdiff_usage(const char *fmt, ...)
288*f3e7f55eSRobert Mustacchi {
289*f3e7f55eSRobert Mustacchi if (fmt != NULL) {
290*f3e7f55eSRobert Mustacchi va_list ap;
291*f3e7f55eSRobert Mustacchi
292*f3e7f55eSRobert Mustacchi (void) fprintf(stderr, "%s: ", g_progname);
293*f3e7f55eSRobert Mustacchi va_start(ap, fmt);
294*f3e7f55eSRobert Mustacchi (void) vfprintf(stderr, fmt, ap);
295*f3e7f55eSRobert Mustacchi va_end(ap);
296*f3e7f55eSRobert Mustacchi }
297*f3e7f55eSRobert Mustacchi
298*f3e7f55eSRobert Mustacchi (void) fprintf(stderr, "Usage: %s [-afIloqt] [-F function] [-O object]"
299*f3e7f55eSRobert Mustacchi "[-p parent] [-P parent]\n"
300*f3e7f55eSRobert Mustacchi "\t[-T type] file1 file2\n"
301*f3e7f55eSRobert Mustacchi "\n"
302*f3e7f55eSRobert Mustacchi "\t-a diff label, types, objects, and functions\n"
303*f3e7f55eSRobert Mustacchi "\t-f diff function type information\n"
304*f3e7f55eSRobert Mustacchi "\t-F when diffing functions, only consider those named\n"
305*f3e7f55eSRobert Mustacchi "\t-I ignore the names of integral types\n"
306*f3e7f55eSRobert Mustacchi "\t-l diff CTF labels\n"
307*f3e7f55eSRobert Mustacchi "\t-o diff global object type information\n"
308*f3e7f55eSRobert Mustacchi "\t-O when diffing objects, only consider those named\n"
309*f3e7f55eSRobert Mustacchi "\t-p set the CTF parent for file1\n"
310*f3e7f55eSRobert Mustacchi "\t-P set the CTF parent for file2\n"
311*f3e7f55eSRobert Mustacchi "\t-q set quiet mode (no diff information sent to stdout)\n"
312*f3e7f55eSRobert Mustacchi "\t-t diff CTF type information\n"
313*f3e7f55eSRobert Mustacchi "\t-T when diffing types, only consider those named\n",
314*f3e7f55eSRobert Mustacchi g_progname);
315*f3e7f55eSRobert Mustacchi }
316*f3e7f55eSRobert Mustacchi
317*f3e7f55eSRobert Mustacchi int
main(int argc,char * argv[])318*f3e7f55eSRobert Mustacchi main(int argc, char *argv[])
319*f3e7f55eSRobert Mustacchi {
320*f3e7f55eSRobert Mustacchi ctf_diff_flag_t flags = 0;
321*f3e7f55eSRobert Mustacchi int err, c;
322*f3e7f55eSRobert Mustacchi ctf_file_t *ifp, *ofp;
323*f3e7f55eSRobert Mustacchi ctf_diff_t *cdp;
324*f3e7f55eSRobert Mustacchi ctf_file_t *pifp = NULL;
325*f3e7f55eSRobert Mustacchi ctf_file_t *pofp = NULL;
326*f3e7f55eSRobert Mustacchi
327*f3e7f55eSRobert Mustacchi g_progname = basename(argv[0]);
328*f3e7f55eSRobert Mustacchi
329*f3e7f55eSRobert Mustacchi while ((c = getopt(argc, argv, ":aqtfolIp:F:O:P:T:")) != -1) {
330*f3e7f55eSRobert Mustacchi switch (c) {
331*f3e7f55eSRobert Mustacchi case 'a':
332*f3e7f55eSRobert Mustacchi g_flag |= CTF_DIFF_ALL;
333*f3e7f55eSRobert Mustacchi break;
334*f3e7f55eSRobert Mustacchi case 't':
335*f3e7f55eSRobert Mustacchi g_flag |= CTF_DIFF_TYPES;
336*f3e7f55eSRobert Mustacchi break;
337*f3e7f55eSRobert Mustacchi case 'f':
338*f3e7f55eSRobert Mustacchi g_flag |= CTF_DIFF_FUNCS;
339*f3e7f55eSRobert Mustacchi break;
340*f3e7f55eSRobert Mustacchi case 'o':
341*f3e7f55eSRobert Mustacchi g_flag |= CTF_DIFF_OBJS;
342*f3e7f55eSRobert Mustacchi break;
343*f3e7f55eSRobert Mustacchi case 'l':
344*f3e7f55eSRobert Mustacchi g_flag |= CTF_DIFF_LABEL;
345*f3e7f55eSRobert Mustacchi break;
346*f3e7f55eSRobert Mustacchi case 'q':
347*f3e7f55eSRobert Mustacchi g_onlydiff = B_TRUE;
348*f3e7f55eSRobert Mustacchi break;
349*f3e7f55eSRobert Mustacchi case 'p':
350*f3e7f55eSRobert Mustacchi pifp = ctf_open(optarg, &err);
351*f3e7f55eSRobert Mustacchi if (pifp == NULL) {
352*f3e7f55eSRobert Mustacchi ctfdiff_fatal("failed to open parent input "
353*f3e7f55eSRobert Mustacchi "container %s: %s\n", optarg,
354*f3e7f55eSRobert Mustacchi ctf_errmsg(err));
355*f3e7f55eSRobert Mustacchi }
356*f3e7f55eSRobert Mustacchi break;
357*f3e7f55eSRobert Mustacchi case 'F':
358*f3e7f55eSRobert Mustacchi if (g_nextfunc == g_nfuncs) {
359*f3e7f55eSRobert Mustacchi if (g_nfuncs == 0)
360*f3e7f55eSRobert Mustacchi g_nfuncs = 16;
361*f3e7f55eSRobert Mustacchi else
362*f3e7f55eSRobert Mustacchi g_nfuncs *= 2;
363*f3e7f55eSRobert Mustacchi g_funclist = realloc(g_funclist,
364*f3e7f55eSRobert Mustacchi sizeof (char *) * g_nfuncs);
365*f3e7f55eSRobert Mustacchi if (g_funclist == NULL) {
366*f3e7f55eSRobert Mustacchi ctfdiff_fatal("failed to allocate "
367*f3e7f55eSRobert Mustacchi "memory for the %dth -F option: "
368*f3e7f55eSRobert Mustacchi "%s\n", g_nexttype + 1,
369*f3e7f55eSRobert Mustacchi strerror(errno));
370*f3e7f55eSRobert Mustacchi }
371*f3e7f55eSRobert Mustacchi }
372*f3e7f55eSRobert Mustacchi g_funclist[g_nextfunc] = optarg;
373*f3e7f55eSRobert Mustacchi g_nextfunc++;
374*f3e7f55eSRobert Mustacchi break;
375*f3e7f55eSRobert Mustacchi case 'O':
376*f3e7f55eSRobert Mustacchi if (g_nextobj == g_nobjs) {
377*f3e7f55eSRobert Mustacchi if (g_nobjs == 0)
378*f3e7f55eSRobert Mustacchi g_nobjs = 16;
379*f3e7f55eSRobert Mustacchi else
380*f3e7f55eSRobert Mustacchi g_nobjs *= 2;
381*f3e7f55eSRobert Mustacchi g_objlist = realloc(g_objlist,
382*f3e7f55eSRobert Mustacchi sizeof (char *) * g_nobjs);
383*f3e7f55eSRobert Mustacchi if (g_objlist == NULL) {
384*f3e7f55eSRobert Mustacchi ctfdiff_fatal("failed to allocate "
385*f3e7f55eSRobert Mustacchi "memory for the %dth -F option: "
386*f3e7f55eSRobert Mustacchi "%s\n", g_nexttype + 1,
387*f3e7f55eSRobert Mustacchi strerror(errno));
388*f3e7f55eSRobert Mustacchi return (CTFDIFF_EXIT_ERROR);
389*f3e7f55eSRobert Mustacchi }
390*f3e7f55eSRobert Mustacchi }
391*f3e7f55eSRobert Mustacchi g_objlist[g_nextobj] = optarg;
392*f3e7f55eSRobert Mustacchi g_nextobj++;
393*f3e7f55eSRobert Mustacchi break;
394*f3e7f55eSRobert Mustacchi case 'I':
395*f3e7f55eSRobert Mustacchi flags |= CTF_DIFF_F_IGNORE_INTNAMES;
396*f3e7f55eSRobert Mustacchi break;
397*f3e7f55eSRobert Mustacchi case 'P':
398*f3e7f55eSRobert Mustacchi pofp = ctf_open(optarg, &err);
399*f3e7f55eSRobert Mustacchi if (pofp == NULL) {
400*f3e7f55eSRobert Mustacchi ctfdiff_fatal("failed to open parent output "
401*f3e7f55eSRobert Mustacchi "container %s: %s\n", optarg,
402*f3e7f55eSRobert Mustacchi ctf_errmsg(err));
403*f3e7f55eSRobert Mustacchi }
404*f3e7f55eSRobert Mustacchi break;
405*f3e7f55eSRobert Mustacchi case 'T':
406*f3e7f55eSRobert Mustacchi if (g_nexttype == g_ntypes) {
407*f3e7f55eSRobert Mustacchi if (g_ntypes == 0)
408*f3e7f55eSRobert Mustacchi g_ntypes = 16;
409*f3e7f55eSRobert Mustacchi else
410*f3e7f55eSRobert Mustacchi g_ntypes *= 2;
411*f3e7f55eSRobert Mustacchi g_typelist = realloc(g_typelist,
412*f3e7f55eSRobert Mustacchi sizeof (char *) * g_ntypes);
413*f3e7f55eSRobert Mustacchi if (g_typelist == NULL) {
414*f3e7f55eSRobert Mustacchi ctfdiff_fatal("failed to allocate "
415*f3e7f55eSRobert Mustacchi "memory for the %dth -T option: "
416*f3e7f55eSRobert Mustacchi "%s\n", g_nexttype + 1,
417*f3e7f55eSRobert Mustacchi strerror(errno));
418*f3e7f55eSRobert Mustacchi }
419*f3e7f55eSRobert Mustacchi }
420*f3e7f55eSRobert Mustacchi g_typelist[g_nexttype] = optarg;
421*f3e7f55eSRobert Mustacchi g_nexttype++;
422*f3e7f55eSRobert Mustacchi break;
423*f3e7f55eSRobert Mustacchi case ':':
424*f3e7f55eSRobert Mustacchi ctfdiff_usage("Option -%c requires an operand\n",
425*f3e7f55eSRobert Mustacchi optopt);
426*f3e7f55eSRobert Mustacchi return (CTFDIFF_EXIT_USAGE);
427*f3e7f55eSRobert Mustacchi case '?':
428*f3e7f55eSRobert Mustacchi ctfdiff_usage("Unknown option: -%c\n", optopt);
429*f3e7f55eSRobert Mustacchi return (CTFDIFF_EXIT_USAGE);
430*f3e7f55eSRobert Mustacchi }
431*f3e7f55eSRobert Mustacchi }
432*f3e7f55eSRobert Mustacchi
433*f3e7f55eSRobert Mustacchi argc -= optind - 1;
434*f3e7f55eSRobert Mustacchi argv += optind - 1;
435*f3e7f55eSRobert Mustacchi
436*f3e7f55eSRobert Mustacchi if (g_flag == 0)
437*f3e7f55eSRobert Mustacchi g_flag = CTF_DIFF_DEFAULT;
438*f3e7f55eSRobert Mustacchi
439*f3e7f55eSRobert Mustacchi if (argc != 3) {
440*f3e7f55eSRobert Mustacchi ctfdiff_usage(NULL);
441*f3e7f55eSRobert Mustacchi return (CTFDIFF_EXIT_USAGE);
442*f3e7f55eSRobert Mustacchi }
443*f3e7f55eSRobert Mustacchi
444*f3e7f55eSRobert Mustacchi if (g_nexttype != 0 && !(g_flag & CTF_DIFF_TYPES)) {
445*f3e7f55eSRobert Mustacchi ctfdiff_usage("-T cannot be used if not diffing types\n");
446*f3e7f55eSRobert Mustacchi return (CTFDIFF_EXIT_USAGE);
447*f3e7f55eSRobert Mustacchi }
448*f3e7f55eSRobert Mustacchi
449*f3e7f55eSRobert Mustacchi if (g_nextfunc != 0 && !(g_flag & CTF_DIFF_FUNCS)) {
450*f3e7f55eSRobert Mustacchi ctfdiff_usage("-F cannot be used if not diffing functions\n");
451*f3e7f55eSRobert Mustacchi return (CTFDIFF_EXIT_USAGE);
452*f3e7f55eSRobert Mustacchi }
453*f3e7f55eSRobert Mustacchi
454*f3e7f55eSRobert Mustacchi if (g_nextobj != 0 && !(g_flag & CTF_DIFF_OBJS)) {
455*f3e7f55eSRobert Mustacchi ctfdiff_usage("-O cannot be used if not diffing objects\n");
456*f3e7f55eSRobert Mustacchi return (CTFDIFF_EXIT_USAGE);
457*f3e7f55eSRobert Mustacchi }
458*f3e7f55eSRobert Mustacchi
459*f3e7f55eSRobert Mustacchi ifp = ctf_open(argv[1], &err);
460*f3e7f55eSRobert Mustacchi if (ifp == NULL) {
461*f3e7f55eSRobert Mustacchi ctfdiff_fatal("failed to open %s: %s\n", argv[1],
462*f3e7f55eSRobert Mustacchi ctf_errmsg(err));
463*f3e7f55eSRobert Mustacchi }
464*f3e7f55eSRobert Mustacchi if (pifp != NULL) {
465*f3e7f55eSRobert Mustacchi err = ctf_import(ifp, pifp);
466*f3e7f55eSRobert Mustacchi if (err != 0) {
467*f3e7f55eSRobert Mustacchi ctfdiff_fatal("failed to set parent container: %s\n",
468*f3e7f55eSRobert Mustacchi ctf_errmsg(ctf_errno(pifp)));
469*f3e7f55eSRobert Mustacchi }
470*f3e7f55eSRobert Mustacchi }
471*f3e7f55eSRobert Mustacchi g_iname = argv[1];
472*f3e7f55eSRobert Mustacchi g_ifp = ifp;
473*f3e7f55eSRobert Mustacchi
474*f3e7f55eSRobert Mustacchi ofp = ctf_open(argv[2], &err);
475*f3e7f55eSRobert Mustacchi if (ofp == NULL) {
476*f3e7f55eSRobert Mustacchi ctfdiff_fatal("failed to open %s: %s\n", argv[2],
477*f3e7f55eSRobert Mustacchi ctf_errmsg(err));
478*f3e7f55eSRobert Mustacchi }
479*f3e7f55eSRobert Mustacchi
480*f3e7f55eSRobert Mustacchi if (pofp != NULL) {
481*f3e7f55eSRobert Mustacchi err = ctf_import(ofp, pofp);
482*f3e7f55eSRobert Mustacchi if (err != 0) {
483*f3e7f55eSRobert Mustacchi ctfdiff_fatal("failed to set parent container: %s\n",
484*f3e7f55eSRobert Mustacchi ctf_errmsg(ctf_errno(pofp)));
485*f3e7f55eSRobert Mustacchi }
486*f3e7f55eSRobert Mustacchi }
487*f3e7f55eSRobert Mustacchi g_oname = argv[2];
488*f3e7f55eSRobert Mustacchi g_ofp = ofp;
489*f3e7f55eSRobert Mustacchi
490*f3e7f55eSRobert Mustacchi if (ctf_diff_init(ifp, ofp, &cdp) != 0) {
491*f3e7f55eSRobert Mustacchi ctfdiff_fatal("failed to initialize libctf diff engine: %s\n",
492*f3e7f55eSRobert Mustacchi ctf_errmsg(ctf_errno(ifp)));
493*f3e7f55eSRobert Mustacchi }
494*f3e7f55eSRobert Mustacchi
495*f3e7f55eSRobert Mustacchi if (ctf_diff_setflags(cdp, flags) != 0) {
496*f3e7f55eSRobert Mustacchi ctfdiff_fatal("failed to set ctfdiff flags: %s\n",
497*f3e7f55eSRobert Mustacchi ctf_errmsg(ctf_errno(ifp)));
498*f3e7f55eSRobert Mustacchi }
499*f3e7f55eSRobert Mustacchi
500*f3e7f55eSRobert Mustacchi err = 0;
501*f3e7f55eSRobert Mustacchi if ((g_flag & CTF_DIFF_TYPES) && err != CTF_ERR)
502*f3e7f55eSRobert Mustacchi err = ctf_diff_types(cdp, ctfdiff_cb, NULL);
503*f3e7f55eSRobert Mustacchi if ((g_flag & CTF_DIFF_FUNCS) && err != CTF_ERR)
504*f3e7f55eSRobert Mustacchi err = ctf_diff_functions(cdp, ctfdiff_func_cb, NULL);
505*f3e7f55eSRobert Mustacchi if ((g_flag & CTF_DIFF_OBJS) && err != CTF_ERR)
506*f3e7f55eSRobert Mustacchi err = ctf_diff_objects(cdp, ctfdiff_obj_cb, NULL);
507*f3e7f55eSRobert Mustacchi if ((g_flag & CTF_DIFF_LABEL) && err != CTF_ERR)
508*f3e7f55eSRobert Mustacchi err = ctfdiff_labels(ifp, ofp);
509*f3e7f55eSRobert Mustacchi
510*f3e7f55eSRobert Mustacchi ctf_diff_fini(cdp);
511*f3e7f55eSRobert Mustacchi if (err == CTF_ERR) {
512*f3e7f55eSRobert Mustacchi ctfdiff_fatal("encountered a libctf error: %s!\n",
513*f3e7f55eSRobert Mustacchi ctf_errmsg(ctf_errno(ifp)));
514*f3e7f55eSRobert Mustacchi }
515*f3e7f55eSRobert Mustacchi
516*f3e7f55eSRobert Mustacchi return (g_different == B_TRUE ? CTFDIFF_EXIT_DIFFERENT :
517*f3e7f55eSRobert Mustacchi CTFDIFF_EXIT_SIMILAR);
518*f3e7f55eSRobert Mustacchi }
519