summaryrefslogtreecommitdiff
path: root/usr/src/cmd/ctfdiff/ctfdiff.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/ctfdiff/ctfdiff.c')
-rw-r--r--usr/src/cmd/ctfdiff/ctfdiff.c220
1 files changed, 220 insertions, 0 deletions
diff --git a/usr/src/cmd/ctfdiff/ctfdiff.c b/usr/src/cmd/ctfdiff/ctfdiff.c
new file mode 100644
index 0000000000..9d4c65e698
--- /dev/null
+++ b/usr/src/cmd/ctfdiff/ctfdiff.c
@@ -0,0 +1,220 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2014 Joyent, Inc. All rights reserved.
+ */
+
+/*
+ * diff two CTF containers
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <strings.h>
+#include <libctf.h>
+
+#define CTFDIFF_EXIT_SIMILAR 0
+#define CTFDIFF_EXIT_DIFFERENT 1
+#define CTFDIFF_EXIT_ERROR 2
+
+static const char *g_iname;
+static ctf_file_t *g_ifp;
+static const char *g_oname;
+static ctf_file_t *g_ofp;
+static char **g_typelist = NULL;
+static int g_nexttype = 0;
+static int g_ntypes = 0;
+static boolean_t g_onlydiff = B_FALSE;
+static boolean_t g_different = B_FALSE;
+
+static const char *
+fp_to_name(ctf_file_t *fp)
+{
+ if (fp == g_ifp)
+ return (g_iname);
+ if (fp == g_ofp)
+ return (g_oname);
+ return (NULL);
+}
+
+/* ARGSUSED */
+static void
+diff_cb(ctf_file_t *ifp, ctf_id_t iid, boolean_t similar, ctf_file_t *ofp,
+ ctf_id_t oid, void *arg)
+{
+ if (similar == B_TRUE)
+ return;
+
+ /*
+ * Check if it's the type the user cares about.
+ */
+ if (g_nexttype != 0) {
+ int i;
+ char namebuf[256];
+
+ if (ctf_type_name(ifp, iid, namebuf, sizeof (namebuf)) ==
+ NULL) {
+ (void) fprintf(stderr, "failed to obtain the name "
+ "of type %ld from %s: %s\n",
+ iid, fp_to_name(ifp),
+ ctf_errmsg(ctf_errno(ifp)));
+ exit(CTFDIFF_EXIT_ERROR);
+ }
+
+ for (i = 0; i < g_nexttype; i++) {
+ if (strcmp(g_typelist[i], namebuf) == 0)
+ break;
+ }
+
+ if (i == g_nexttype)
+ return;
+ }
+
+ g_different = B_TRUE;
+
+ if (g_onlydiff == B_TRUE)
+ return;
+
+ (void) printf("fp %s type %ld ", fp_to_name(ifp), iid);
+ if (similar == B_TRUE) {
+ (void) printf("is the same as fp %s type %ld\n",
+ fp_to_name(ofp), oid);
+ } else {
+ (void) printf("is different\n");
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ ctf_diff_flag_t flags = 0;
+ int err, c;
+ ctf_file_t *ifp, *ofp;
+ ctf_diff_t *cdp;
+ ctf_file_t *pifp = NULL;
+ ctf_file_t *pofp = NULL;
+
+ while ((c = getopt(argc, argv, "qIp:P:T:")) != -1) {
+ switch (c) {
+ case 'q':
+ g_onlydiff = B_TRUE;
+ break;
+ case 'p':
+ pifp = ctf_open(optarg, &err);
+ if (pifp == NULL) {
+ (void) fprintf(stderr, "ctfdiff: failed to "
+ "open parent input container %s: %s\n",
+ optarg, ctf_errmsg(err));
+ return (CTFDIFF_EXIT_ERROR);
+ }
+ break;
+ case 'I':
+ flags |= CTF_DIFF_F_IGNORE_INTNAMES;
+ break;
+ case 'P':
+ pofp = ctf_open(optarg, &err);
+ if (pofp == NULL) {
+ (void) fprintf(stderr, "ctfdiff: failed to "
+ "open parent output container %s: %s\n",
+ optarg, ctf_errmsg(err));
+ return (CTFDIFF_EXIT_ERROR);
+ }
+ break;
+ case 'T':
+ if (g_nexttype == g_ntypes) {
+ if (g_ntypes == 0)
+ g_ntypes = 16;
+ else
+ g_ntypes *= 2;
+ g_typelist = realloc(g_typelist,
+ sizeof (char *) * g_ntypes);
+ if (g_typelist == NULL) {
+ (void) fprintf(stderr, "ctfdiff: "
+ "failed to allocate memory for "
+ "the %dth -t option: %s\n",
+ g_nexttype + 1, strerror(errno));
+ }
+ }
+ g_typelist[g_nexttype] = optarg;
+ g_nexttype++;
+ }
+ }
+
+ argc -= optind - 1;
+ argv += optind - 1;
+
+ if (argc != 3) {
+ (void) fprintf(stderr, "usage: ctfdiff [-qI] [-p parent] "
+ "[-P parent] [-T type]... input output");
+ return (CTFDIFF_EXIT_ERROR);
+ }
+
+ ifp = ctf_open(argv[1], &err);
+ if (ifp == NULL) {
+ (void) fprintf(stderr, "ctfdiff: failed to open %s: %s\n",
+ argv[1], ctf_errmsg(err));
+ return (CTFDIFF_EXIT_ERROR);
+ }
+ if (pifp != NULL) {
+ err = ctf_import(ifp, pifp);
+ if (err != 0) {
+ (void) fprintf(stderr, "ctfdiff: failed to set parent "
+ "container: %s\n", ctf_errmsg(ctf_errno(pifp)));
+ return (CTFDIFF_EXIT_ERROR);
+ }
+ }
+ g_iname = argv[1];
+ g_ifp = ifp;
+
+ ofp = ctf_open(argv[2], &err);
+ if (ofp == NULL) {
+ (void) fprintf(stderr, "ctfdiff: failed to open %s: %s\n",
+ argv[2], ctf_errmsg(err));
+ return (CTFDIFF_EXIT_ERROR);
+ }
+
+ if (pofp != NULL) {
+ err = ctf_import(ofp, pofp);
+ if (err != 0) {
+ (void) fprintf(stderr, "ctfdiff: failed to set parent "
+ "container: %s\n", ctf_errmsg(ctf_errno(pofp)));
+ return (CTFDIFF_EXIT_ERROR);
+ }
+ }
+ g_oname = argv[2];
+ g_ofp = ofp;
+
+ if (ctf_diff_init(ifp, ofp, &cdp) != 0) {
+ (void) fprintf(stderr,
+ "ctfdiff: failed to initialize libctf diff engine: %s\n",
+ ctf_errmsg(ctf_errno(ifp)));
+ return (CTFDIFF_EXIT_ERROR);
+ }
+
+ if (ctf_diff_setflags(cdp, flags) != 0) {
+ (void) fprintf(stderr,
+ "ctfdiff: failed to set ctfdiff flags: %s\n",
+ ctf_errmsg(ctf_errno(ifp)));
+ }
+
+ err = ctf_diff_types(cdp, diff_cb, NULL);
+ ctf_diff_fini(cdp);
+ if (err == CTF_ERR) {
+ (void) fprintf(stderr, "encountered a libctf error: %s!\n",
+ ctf_errmsg(ctf_errno(ifp)));
+ return (CTFDIFF_EXIT_ERROR);
+ }
+
+ return (g_different == B_TRUE ? CTFDIFF_EXIT_DIFFERENT :
+ CTFDIFF_EXIT_SIMILAR);
+}