xref: /titanic_51/usr/src/cmd/ctfdiff/ctfdiff.c (revision 7fd791373689a6af05e27efec3b1ab556e02aa23)
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
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 *
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
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
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
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
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
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
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
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
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