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