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