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