summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@joyent.com>2014-07-12 00:48:08 +0000
committerRobert Mustacchi <rm@joyent.com>2014-07-18 22:22:02 +0000
commit4bd0c2b79d9b19403df4764e4b7941b29abe4a80 (patch)
tree2780b304153df871a1dcc9ec991ae4ff57211d7f
parent1fba5429ccf7095093d8035f56380cf7b125f0f2 (diff)
downloadillumos-joyent-4bd0c2b79d9b19403df4764e4b7941b29abe4a80.tar.gz
OS-3203 want check target for verifying structures are the same in ILP32 and LP64
Reviewed by: Keith M Wesolowski <wesolows@foobazco.org>
-rw-r--r--manifest2
-rw-r--r--usr/src/Makefile.master1
-rw-r--r--usr/src/cmd/Makefile1
-rw-r--r--usr/src/cmd/ctfdiff/Makefile44
-rw-r--r--usr/src/cmd/ctfdiff/ctfdiff.c220
-rw-r--r--usr/src/cmd/mdb/Makefile.common1
-rw-r--r--usr/src/cmd/mdb/common/modules/ctf/mdb_modctf.c85
-rw-r--r--usr/src/cmd/mdb/intel/amd64/libctf/Makefile26
-rw-r--r--usr/src/cmd/mdb/intel/ia32/libctf/Makefile25
-rw-r--r--usr/src/cmd/mdb/sparc/v7/libctf/Makefile25
-rw-r--r--usr/src/cmd/mdb/sparc/v9/libctf/Makefile26
-rw-r--r--usr/src/common/ctf/ctf_create.c2
-rw-r--r--usr/src/common/ctf/ctf_hash.c160
-rw-r--r--usr/src/common/ctf/ctf_impl.h6
-rw-r--r--usr/src/common/ctf/ctf_types.c64
-rw-r--r--usr/src/lib/Makefile.lib12
-rw-r--r--usr/src/lib/Makefile.targ3
-rw-r--r--usr/src/lib/libctf/Makefile.com41
-rw-r--r--usr/src/lib/libctf/Makefile.shared.com67
-rw-r--r--usr/src/lib/libctf/Makefile.shared.targ22
-rw-r--r--usr/src/lib/libctf/common/ctf_diff.c783
-rw-r--r--usr/src/lib/libctf/common/libctf.h20
-rw-r--r--usr/src/lib/libctf/common/mapfile-vers17
-rw-r--r--usr/src/lib/libvnd/Makefile10
-rw-r--r--usr/src/tools/ctf/Makefile2
-rw-r--r--usr/src/tools/ctf/Makefile.ctf1
-rw-r--r--usr/src/tools/ctf/common/ctf_headers.h1
-rw-r--r--usr/src/tools/ctf/ctfdiff/Makefile44
-rw-r--r--usr/src/tools/ctf/ctfdiff/Makefile.com44
-rw-r--r--usr/src/tools/ctf/ctfdiff/i386/Makefile27
-rw-r--r--usr/src/tools/ctf/ctfdiff/sparc/Makefile27
-rw-r--r--usr/src/tools/ctf/libctf/Makefile46
-rw-r--r--usr/src/tools/ctf/libctf/Makefile.com42
-rw-r--r--usr/src/tools/ctf/libctf/i386/Makefile8
-rw-r--r--usr/src/tools/ctf/libctf/sparc/Makefile8
-rw-r--r--usr/src/uts/common/sys/ctf_api.h30
36 files changed, 1896 insertions, 47 deletions
diff --git a/manifest b/manifest
index 7e34c440a1..3c7b98a1d9 100644
--- a/manifest
+++ b/manifest
@@ -9595,6 +9595,7 @@ f usr/lib/mdb/proc/amd64/ld.so 0555 root sys
f usr/lib/mdb/proc/amd64/libavl.so 0555 root sys
f usr/lib/mdb/proc/amd64/libc.so 0555 root sys
f usr/lib/mdb/proc/amd64/libcmdutils.so 0555 root sys
+f usr/lib/mdb/proc/amd64/libctf.so 0555 root sys
f usr/lib/mdb/proc/amd64/libnvpair.so 0555 root sys
f usr/lib/mdb/proc/amd64/libproc.so 0555 root sys
f usr/lib/mdb/proc/amd64/libpython2.6.so 0555 root sys
@@ -9612,6 +9613,7 @@ f usr/lib/mdb/proc/ld.so 0555 root sys
f usr/lib/mdb/proc/libavl.so 0555 root sys
f usr/lib/mdb/proc/libc.so 0555 root sys
f usr/lib/mdb/proc/libcmdutils.so 0555 root sys
+f usr/lib/mdb/proc/libctf.so 0555 root sys
f usr/lib/mdb/proc/libnvpair.so 0555 root sys
f usr/lib/mdb/proc/libproc.so 0555 root sys
f usr/lib/mdb/proc/libpython2.6.so 0555 root sys
diff --git a/usr/src/Makefile.master b/usr/src/Makefile.master
index 920202ac40..63a46e0468 100644
--- a/usr/src/Makefile.master
+++ b/usr/src/Makefile.master
@@ -155,6 +155,7 @@ JAVADOC= $(JAVA_ROOT)/bin/javadoc
RMIC= $(JAVA_ROOT)/bin/rmic
JAR= $(JAVA_ROOT)/bin/jar
CTFCONVERT= $(ONBLD_TOOLS)/bin/$(MACH)/ctfconvert
+CTFDIFF= $(ONBLD_TOOLS)/bin/$(MACH)/ctfdiff
CTFMERGE= $(ONBLD_TOOLS)/bin/$(MACH)/ctfmerge
CTFSTABS= $(ONBLD_TOOLS)/bin/$(MACH)/ctfstabs
CTFSTRIP= $(ONBLD_TOOLS)/bin/$(MACH)/ctfstrip
diff --git a/usr/src/cmd/Makefile b/usr/src/cmd/Makefile
index e1725a776b..5d5404299b 100644
--- a/usr/src/cmd/Makefile
+++ b/usr/src/cmd/Makefile
@@ -104,6 +104,7 @@ COMMON_SUBDIRS= \
crypt \
csh \
csplit \
+ ctfdiff \
ctrun \
ctstat \
ctwatch \
diff --git a/usr/src/cmd/ctfdiff/Makefile b/usr/src/cmd/ctfdiff/Makefile
new file mode 100644
index 0000000000..5779f280bc
--- /dev/null
+++ b/usr/src/cmd/ctfdiff/Makefile
@@ -0,0 +1,44 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+PROG= ctfdiff
+
+include ../Makefile.cmd
+
+CFLAGS += $(CCVERBOSE)
+LDLIBS += -lctf
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+install: all $(ROOTPROG)
+
+clean:
+
+lint: lint_PROG
+
+include ../Makefile.targ
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);
+}
diff --git a/usr/src/cmd/mdb/Makefile.common b/usr/src/cmd/mdb/Makefile.common
index b78836c741..ea319d65ae 100644
--- a/usr/src/cmd/mdb/Makefile.common
+++ b/usr/src/cmd/mdb/Makefile.common
@@ -28,6 +28,7 @@ COMMON_MODULES_PROC = \
dof \
libavl \
libc \
+ libctf \
libcmdutils \
libnvpair \
libproc \
diff --git a/usr/src/cmd/mdb/common/modules/ctf/mdb_modctf.c b/usr/src/cmd/mdb/common/modules/ctf/mdb_modctf.c
new file mode 100644
index 0000000000..5c946c938e
--- /dev/null
+++ b/usr/src/cmd/mdb/common/modules/ctf/mdb_modctf.c
@@ -0,0 +1,85 @@
+/*
+ * 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) 2013 Joyent, Inc. All rights reserved.
+ */
+
+/*
+ * Routines for debugging ctf containers
+ */
+
+#include <mdb/mdb_modapi.h>
+#include <ctf_impl.h>
+
+static int
+mdb_ctf_idhash_walk_init(mdb_walk_state_t *wsp)
+{
+ ctf_idhash_t *ihp;
+
+ if (wsp->walk_addr == NULL) {
+ mdb_warn("ctf_idhash walker does not support global walks\n");
+ return (WALK_ERR);
+ }
+
+ ihp = mdb_alloc(sizeof (ctf_idhash_t), UM_NOSLEEP | UM_GC);
+ if (ihp == NULL) {
+ mdb_warn("failed to allocate memory for a ctf_idhash_t");
+ return (WALK_ERR);
+ }
+
+ if (mdb_vread(ihp, sizeof (ctf_idhash_t), wsp->walk_addr) !=
+ sizeof (ctf_idhash_t)) {
+ mdb_warn("failed to read ctf_idhash_t at %p", wsp->walk_addr);
+ return (WALK_ERR);
+ }
+
+ if (ihp->ih_free == 0)
+ return (WALK_DONE);
+ wsp->walk_data = ihp;
+ wsp->walk_arg = (void *)(uintptr_t)1;
+
+ return (WALK_NEXT);
+}
+
+static int
+mdb_ctf_idhash_walk_step(mdb_walk_state_t *wsp)
+{
+ ctf_ihelem_t ihe;
+ ctf_idhash_t *ihp = wsp->walk_data;
+ int index = (uintptr_t)wsp->walk_arg;
+
+ if (index == ihp->ih_free)
+ return (WALK_DONE);
+
+ if (mdb_vread(&ihe, sizeof (ihe),
+ (uintptr_t)(ihp->ih_chains + index)) != sizeof (ihe)) {
+ mdb_warn("failed to read index %d at %p", index,
+ ihp->ih_chains + index);
+ return (WALK_ERR);
+ }
+ wsp->walk_arg = (void *)(uintptr_t)(index + 1);
+ return (wsp->walk_callback((uintptr_t)(ihp->ih_chains + index), &ihe,
+ wsp->walk_cbdata));
+}
+
+static const mdb_walker_t walkers[] = {
+ { "ctf_idhash", "walk entries in a ctf idhash",
+ mdb_ctf_idhash_walk_init, mdb_ctf_idhash_walk_step }
+};
+
+static const mdb_modinfo_t modinfo = { MDB_API_VERSION, NULL, walkers };
+
+const mdb_modinfo_t *
+_mdb_init(void)
+{
+ return (&modinfo);
+}
diff --git a/usr/src/cmd/mdb/intel/amd64/libctf/Makefile b/usr/src/cmd/mdb/intel/amd64/libctf/Makefile
new file mode 100644
index 0000000000..a65e7bd2e8
--- /dev/null
+++ b/usr/src/cmd/mdb/intel/amd64/libctf/Makefile
@@ -0,0 +1,26 @@
+#
+# 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) 2013, Joyent, Inc. All rights reserved.
+#
+
+MODULE = libctf.so
+MDBTGT = proc
+MODSRCS = mdb_modctf.c
+
+include ../../../../Makefile.cmd
+include ../../../../Makefile.cmd.64
+include ../../Makefile.amd64
+include ../../../Makefile.module
+
+MODSRCS_DIR = ../../../common/modules/ctf
+CPPFLAGS += -I$(SRC)/common/ctf
diff --git a/usr/src/cmd/mdb/intel/ia32/libctf/Makefile b/usr/src/cmd/mdb/intel/ia32/libctf/Makefile
new file mode 100644
index 0000000000..16923da4fe
--- /dev/null
+++ b/usr/src/cmd/mdb/intel/ia32/libctf/Makefile
@@ -0,0 +1,25 @@
+#
+# 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) 2013, Joyent, Inc. All rights reserved.
+#
+
+MODULE = libctf.so
+MDBTGT = proc
+MODSRCS = mdb_modctf.c
+
+include ../../../../Makefile.cmd
+include ../../Makefile.ia32
+include ../../../Makefile.module
+
+MODSRCS_DIR = ../../../common/modules/ctf
+CPPFLAGS += -I$(SRC)/common/ctf
diff --git a/usr/src/cmd/mdb/sparc/v7/libctf/Makefile b/usr/src/cmd/mdb/sparc/v7/libctf/Makefile
new file mode 100644
index 0000000000..477cf40df5
--- /dev/null
+++ b/usr/src/cmd/mdb/sparc/v7/libctf/Makefile
@@ -0,0 +1,25 @@
+#
+# 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) 2013, Joyent, Inc. All rights reserved.
+#
+
+MODULE = libctf.so
+MDBTGT = proc
+MODSRCS = mdb_modctf.c
+
+include ../../../../Makefile.cmd
+include ../../Makefile.sparcv7
+include ../../../Makefile.module
+
+MODSRCS_DIR = ../../../common/modules/ctf
+CPPFLAGS += -I$(SRC)/common/ctf
diff --git a/usr/src/cmd/mdb/sparc/v9/libctf/Makefile b/usr/src/cmd/mdb/sparc/v9/libctf/Makefile
new file mode 100644
index 0000000000..a55126e198
--- /dev/null
+++ b/usr/src/cmd/mdb/sparc/v9/libctf/Makefile
@@ -0,0 +1,26 @@
+#
+# 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) 2013, Joyent, Inc. All rights reserved.
+#
+
+MODULE = libctf.so
+MDBTGT = proc
+MODSRCS = mdb_modctf.c
+
+include ../../../../Makefile.cmd
+include ../../../../Makefile.cmd.64
+include ../../Makefile.sparcv9
+include ../../../Makefile.module
+
+MODSRCS_DIR = ../../../common/modules/ctf
+CPPFLAGS += -I$(SRC)/common/ctf
diff --git a/usr/src/common/ctf/ctf_create.c b/usr/src/common/ctf/ctf_create.c
index 239d166f44..f9feca81cf 100644
--- a/usr/src/common/ctf/ctf_create.c
+++ b/usr/src/common/ctf/ctf_create.c
@@ -574,7 +574,7 @@ ctf_dtd_lookup(ctf_file_t *fp, ctf_id_t type)
int
ctf_discard(ctf_file_t *fp)
{
- ctf_dtdef_t *dtd, *ntd;
+ ctf_dtdef_t *dtd, *ntd = NULL;
if (!(fp->ctf_flags & LCTF_RDWR))
return (ctf_set_errno(fp, ECTF_RDONLY));
diff --git a/usr/src/common/ctf/ctf_hash.c b/usr/src/common/ctf/ctf_hash.c
index b10a7618f6..e68fe8e516 100644
--- a/usr/src/common/ctf/ctf_hash.c
+++ b/usr/src/common/ctf/ctf_hash.c
@@ -25,9 +25,8 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <ctf_impl.h>
+#include <sys/debug.h>
static const ushort_t _CTF_EMPTY[1] = { 0 };
@@ -176,3 +175,160 @@ ctf_hash_destroy(ctf_hash_t *hp)
hp->h_chains = NULL;
}
}
+
+int
+ctf_idhash_create(ctf_idhash_t *ihp, ulong_t nelems)
+{
+ if (nelems > USHRT_MAX)
+ return (EOVERFLOW);
+
+ /*
+ * If the hash table is going to be empty, don't bother allocating any
+ * memory and make the only bucket point to a zero so lookups fail.
+ */
+ if (nelems == 0) {
+ bzero(ihp, sizeof (ctf_idhash_t));
+ ihp->ih_buckets = (ushort_t *)_CTF_EMPTY;
+ ihp->ih_nbuckets = 1;
+ return (0);
+ }
+
+ ihp->ih_nbuckets = 211; /* use a prime number of hash buckets */
+ ihp->ih_nelems = nelems + 1; /* we use index zero as a sentinel */
+ ihp->ih_free = 1; /* first free element is index 1 */
+
+ ihp->ih_buckets = ctf_alloc(sizeof (ushort_t) * ihp->ih_nbuckets);
+ ihp->ih_chains = ctf_alloc(sizeof (ctf_ihelem_t) * ihp->ih_nelems);
+
+ if (ihp->ih_buckets == NULL || ihp->ih_chains == NULL) {
+ ctf_idhash_destroy(ihp);
+ return (EAGAIN);
+ }
+
+ bzero(ihp->ih_buckets, sizeof (ushort_t) * ihp->ih_nbuckets);
+ bzero(ihp->ih_chains, sizeof (ctf_ihelem_t) * ihp->ih_nelems);
+
+ return (0);
+}
+
+void
+ctf_idhash_clear(ctf_idhash_t *ihp)
+{
+ /* Nothing to do for a sentinel hash */
+ if (ihp->ih_nbuckets == 1) {
+ ASSERT(ihp->ih_buckets == (ushort_t *)_CTF_EMPTY);
+ return;
+ }
+
+ ihp->ih_free = 1;
+ bzero(ihp->ih_buckets, sizeof (ushort_t) * ihp->ih_nbuckets);
+ bzero(ihp->ih_chains, sizeof (ctf_ihelem_t) * ihp->ih_nelems);
+}
+
+uint_t
+ctf_idhash_size(const ctf_idhash_t *hp)
+{
+ return (hp->ih_nelems ? hp->ih_nelems - 1 : 0);
+}
+
+static ulong_t
+ctf_idhash_compute(ctf_id_t id)
+{
+ return (id);
+}
+
+int
+ctf_idhash_insert(ctf_idhash_t *ihp, ushort_t type, ushort_t value)
+{
+ ctf_ihelem_t *ihep = &ihp->ih_chains[ihp->ih_free];
+ ulong_t h;
+
+ if (ihp->ih_free >= ihp->ih_nelems)
+ return (EOVERFLOW);
+
+ ihep->ih_type = type;
+ ihep->ih_value = value;
+ h = ctf_idhash_compute(type) % ihp->ih_nbuckets;
+ ihep->ih_next = ihp->ih_buckets[h];
+ ihp->ih_buckets[h] = ihp->ih_free++;
+
+ return (0);
+}
+
+int
+ctf_idhash_define(ctf_idhash_t *ihp, ushort_t type, ushort_t value)
+{
+ ctf_ihelem_t *hep = ctf_idhash_lookup(ihp, type);
+
+ if (hep == NULL)
+ return (ctf_idhash_insert(ihp, type, value));
+
+ hep->ih_value = value;
+ return (0);
+}
+
+
+ctf_ihelem_t *
+ctf_idhash_lookup(ctf_idhash_t *ihp, ushort_t key)
+{
+ ctf_ihelem_t *ihep;
+ ushort_t i;
+
+ ulong_t h = ctf_idhash_compute(key) % ihp->ih_nbuckets;
+
+ for (i = ihp->ih_buckets[h]; i != 0; i = ihep->ih_next) {
+ ihep = &ihp->ih_chains[i];
+
+ if (ihep->ih_type == key)
+ return (ihep);
+ }
+
+ return (NULL);
+}
+
+void
+ctf_idhash_destroy(ctf_idhash_t *ihp)
+{
+ if (ihp->ih_buckets != NULL && ihp->ih_nbuckets != 1) {
+ ctf_free(ihp->ih_buckets, sizeof (ushort_t) * ihp->ih_nbuckets);
+ ihp->ih_buckets = NULL;
+ }
+
+ if (ihp->ih_chains != NULL) {
+ ctf_free(ihp->ih_chains, sizeof (ctf_helem_t) * ihp->ih_nelems);
+ ihp->ih_chains = NULL;
+ }
+}
+
+/*ARGSUSED*/
+int
+ctf_idhash_iter_init(ctf_idhash_t *ihp, ctf_idhash_iter_t **iterp)
+{
+
+ *iterp = ctf_alloc(sizeof (ctf_idhash_iter_t));
+ if (*iterp == NULL)
+ return (ENOMEM);
+
+ if (ihp->ih_free == 0)
+ (*iterp)->cii_id = 0;
+ else
+ (*iterp)->cii_id = 1;
+
+ return (0);
+}
+
+const ctf_ihelem_t *
+ctf_idhash_iter(ctf_idhash_t *ihp, ctf_idhash_iter_t *iter)
+{
+ if (iter->cii_id >= ihp->ih_free)
+ return (NULL);
+
+ return (&ihp->ih_chains[iter->cii_id++]);
+}
+
+/*ARGSUSED*/
+void
+ctf_idhash_iter_fini(ctf_idhash_t *ihp, ctf_idhash_iter_t *iter)
+{
+ ctf_free(iter, sizeof (ctf_idhash_iter_t));
+}
diff --git a/usr/src/common/ctf/ctf_impl.h b/usr/src/common/ctf/ctf_impl.h
index f56fa6a005..42aec80a43 100644
--- a/usr/src/common/ctf/ctf_impl.h
+++ b/usr/src/common/ctf/ctf_impl.h
@@ -25,7 +25,7 @@
* Use is subject to license terms.
*/
/*
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2014, Joyent, Inc. All rights reserved.
*/
#ifndef _CTF_IMPL_H
@@ -77,6 +77,10 @@ typedef struct ctf_hash {
uint_t h_free; /* index of next free hash element */
} ctf_hash_t;
+struct ctf_idhash_iter {
+ int cii_id; /* Current iteration id */
+};
+
typedef struct ctf_strs {
const char *cts_strs; /* base address of string table */
size_t cts_len; /* size of string table in bytes */
diff --git a/usr/src/common/ctf/ctf_types.c b/usr/src/common/ctf/ctf_types.c
index ab1b9ff14b..93168f25cb 100644
--- a/usr/src/common/ctf/ctf_types.c
+++ b/usr/src/common/ctf/ctf_types.c
@@ -26,6 +26,7 @@
*/
#include <ctf_impl.h>
+#include <sys/debug.h>
ssize_t
ctf_get_ctt_size(const ctf_file_t *fp, const ctf_type_t *tp, ssize_t *sizep,
@@ -868,3 +869,66 @@ ctf_type_visit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg)
{
return (ctf_type_rvisit(fp, type, func, arg, "", 0, 0));
}
+
+int
+ctf_func_info_by_id(ctf_file_t *fp, ctf_id_t type, ctf_funcinfo_t *fip)
+{
+ ctf_file_t *ofp = fp;
+ const ctf_type_t *tp;
+ const ushort_t *dp;
+ int nargs;
+ ssize_t increment;
+
+ if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
+ return (CTF_ERR); /* errno is set for us */
+
+ if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_FUNCTION)
+ return (ctf_set_errno(ofp, ECTF_NOTFUNC));
+
+ fip->ctc_return = tp->ctt_type;
+ nargs = LCTF_INFO_VLEN(fp, tp->ctt_info);
+ fip->ctc_argc = nargs;
+ fip->ctc_flags = 0;
+
+ /* dp should now point to the first argument */
+ if (nargs != 0) {
+ (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
+ dp = (ushort_t *)((uintptr_t)fp->ctf_buf +
+ fp->ctf_txlate[CTF_TYPE_TO_INDEX(type)] + increment);
+ if (dp[nargs - 1] == 0) {
+ fip->ctc_flags |= CTF_FUNC_VARARG;
+ fip->ctc_argc--;
+ }
+ }
+
+ return (0);
+}
+
+int
+ctf_func_args_by_id(ctf_file_t *fp, ctf_id_t type, uint_t argc, ctf_id_t *argv)
+{
+ ctf_file_t *ofp = fp;
+ const ctf_type_t *tp;
+ const ushort_t *dp;
+ int nargs;
+ ssize_t increment;
+
+ if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
+ return (CTF_ERR); /* errno is set for us */
+
+ if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_FUNCTION)
+ return (ctf_set_errno(ofp, ECTF_NOTFUNC));
+
+ nargs = LCTF_INFO_VLEN(fp, tp->ctt_info);
+ (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
+ dp = (ushort_t *)((uintptr_t)fp->ctf_buf +
+ fp->ctf_txlate[CTF_TYPE_TO_INDEX(type)] +
+ increment);
+ if (nargs != 0 && dp[nargs - 1] == 0)
+ nargs--;
+
+ for (nargs = MIN(argc, nargs); nargs != 0; nargs--)
+ *argv++ = *dp++;
+
+ return (0);
+}
diff --git a/usr/src/lib/Makefile.lib b/usr/src/lib/Makefile.lib
index 78ef2cd4b5..eeb89960f4 100644
--- a/usr/src/lib/Makefile.lib
+++ b/usr/src/lib/Makefile.lib
@@ -251,3 +251,15 @@ TARGETMACH= $(MACH)
# shouldn't override this - they should override $(CLOBBERFILES) instead.
#
CLOBBERTARGFILES= $(LIBS) $(DYNLIB) $(CLOBBERFILES)
+
+#
+# Define the default ctfdiff invocation used to check a list of types
+# supplied by a user of a library. The goal is to validate that a given
+# series of types is the same in both a 32-bit and 64-bit artifact. This
+# is only defined if we have a 64-bit build to do.
+#
+TYPECHECK_LIB32 = $(TYPECHECK_LIB:%=$(MACH)/%)
+TYPECHECK_LIB64 = $(TYPECHECK_LIB:%=$(MACH64)/%)
+TYPECHECK_LIST= $(TYPELIST:%=-T %)
+$(BUILD64)TYPECHECK.lib = $(CTFDIFF) -I $(TYPECHECK_LIST) $(TYPECHECK_LIB32) $(TYPECHECK_LIB64)
+TYPECHECK = $(TYPECHECK_LIB:%=%.typecheck)
diff --git a/usr/src/lib/Makefile.targ b/usr/src/lib/Makefile.targ
index 4769c64d54..61cb45969d 100644
--- a/usr/src/lib/Makefile.targ
+++ b/usr/src/lib/Makefile.targ
@@ -104,6 +104,9 @@ $(LINTLIB): $$(SRCS)
lintcheck: $$(SRCS)
$(LINT.c) $(LINTCHECKFLAGS) $(SRCS) $(LDLIBS)
+$(TYPECHECK): $(TYPECHECK_LIB32) $(TYPECHECK_LIB64)
+ $(TYPECHECK.lib)
+
clobber: clean
-$(RM) $(CLOBBERTARGFILES)
diff --git a/usr/src/lib/libctf/Makefile.com b/usr/src/lib/libctf/Makefile.com
index 4d1e01d4eb..0169c2a367 100644
--- a/usr/src/lib/libctf/Makefile.com
+++ b/usr/src/lib/libctf/Makefile.com
@@ -23,43 +23,9 @@
# Use is subject to license terms.
#
-LIBRARY = libctf.a
-VERS = .1
-
-COMMON_OBJS = \
- ctf_create.o \
- ctf_decl.o \
- ctf_error.o \
- ctf_hash.o \
- ctf_labels.o \
- ctf_lookup.o \
- ctf_open.o \
- ctf_types.o \
- ctf_util.o
-
-LIB_OBJS = \
- ctf_lib.o \
- ctf_subr.o
-
-OBJECTS = $(COMMON_OBJS) $(LIB_OBJS)
-
-include ../../Makefile.lib
+include ../Makefile.shared.com
include ../../Makefile.rootfs
-SRCS = $(COMMON_OBJS:%.o=../../../common/ctf/%.c) $(LIB_OBJS:%.o=../common/%.c)
-LIBS = $(DYNLIB) $(LINTLIB)
-
-SRCDIR = ../common
-
-CPPFLAGS += -I../common -I../../../common/ctf -DCTF_OLD_VERSIONS
-CFLAGS += $(CCVERBOSE)
-
-CERRWARN += -_gcc=-Wno-uninitialized
-
-LDLIBS += -lc
-
-$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
-
.KEEP_STATE:
all: $(LIBS)
@@ -67,7 +33,4 @@ all: $(LIBS)
lint: lintcheck
include ../../Makefile.targ
-
-objs/%.o pics/%.o: ../../../common/ctf/%.c
- $(COMPILE.c) -o $@ $<
- $(POST_PROCESS_O)
+include ../Makefile.shared.targ
diff --git a/usr/src/lib/libctf/Makefile.shared.com b/usr/src/lib/libctf/Makefile.shared.com
new file mode 100644
index 0000000000..92f33a93b6
--- /dev/null
+++ b/usr/src/lib/libctf/Makefile.shared.com
@@ -0,0 +1,67 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright (c) 2014, Joyent, Inc. All rights reserved.
+#
+
+#
+# This Makefile is shared between the libctf native build in tools and
+# the libctf build here for the system.
+#
+LIBRARY = libctf.a
+VERS = .1
+
+COMMON_OBJS = \
+ ctf_create.o \
+ ctf_decl.o \
+ ctf_error.o \
+ ctf_hash.o \
+ ctf_labels.o \
+ ctf_lookup.o \
+ ctf_open.o \
+ ctf_types.o \
+ ctf_util.o
+
+LIB_OBJS = \
+ ctf_diff.o \
+ ctf_lib.o \
+ ctf_subr.o
+
+OBJECTS = $(COMMON_OBJS) $(LIB_OBJS)
+MAPFILEDIR = $(SRC)/lib/libctf
+
+include $(SRC)/lib/Makefile.lib
+
+SRCS = $(COMMON_OBJS:%.o=$(SRC)/common/ctf/%.c) $(LIB_OBJS:%.o=$(SRC)/lib/libctf/common/%.c)
+LIBS = $(DYNLIB) $(LINTLIB)
+LDLIBS = -lc
+
+SRCDIR = $(SRC)/lib/libctf/common
+
+CPPFLAGS += -I$(SRC)/lib/libctf/common -I$(SRC)/common/ctf -DCTF_OLD_VERSIONS
+CFLAGS += $(CCVERBOSE)
+
+CERRWARN += -_gcc=-Wno-uninitialized
+
+$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
diff --git a/usr/src/lib/libctf/Makefile.shared.targ b/usr/src/lib/libctf/Makefile.shared.targ
new file mode 100644
index 0000000000..7fc28aefcd
--- /dev/null
+++ b/usr/src/lib/libctf/Makefile.shared.targ
@@ -0,0 +1,22 @@
+#
+# 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.
+#
+
+#
+# This Makefile is shared between both the tools and the normal library build.
+#
+
+pics/%.o: $(SRC)/common/ctf/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
diff --git a/usr/src/lib/libctf/common/ctf_diff.c b/usr/src/lib/libctf/common/ctf_diff.c
new file mode 100644
index 0000000000..aabfd38fcf
--- /dev/null
+++ b/usr/src/lib/libctf/common/ctf_diff.c
@@ -0,0 +1,783 @@
+/*
+ * 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.
+ */
+
+#include <libctf.h>
+#include <ctf_impl.h>
+#include <sys/debug.h>
+
+/* typedef in libctf.h */
+struct ctf_diff {
+ uint_t cds_flags;
+ ctf_file_t *cds_ifp;
+ ctf_file_t *cds_ofp;
+ ctf_idhash_t cds_forward;
+ ctf_idhash_t cds_reverse;
+ ctf_idhash_t cds_fneg;
+ ctf_idhash_t cds_f_visited;
+ ctf_idhash_t cds_r_visited;
+ ctf_diff_type_f cds_func;
+ int cds_visitid;
+ void *cds_arg;
+};
+
+/*
+ * Team Diff
+ */
+static int ctf_diff_type(ctf_diff_t *, ctf_file_t *, ctf_id_t, ctf_file_t *,
+ ctf_id_t);
+
+static int
+ctf_diff_name(ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp, ctf_id_t oid)
+{
+ const char *iname, *oname;
+ const ctf_type_t *itp, *otp;
+
+ if ((itp = ctf_lookup_by_id(&ifp, iid)) == NULL)
+ return (CTF_ERR);
+
+ if ((otp = ctf_lookup_by_id(&ofp, oid)) == NULL)
+ return (ctf_set_errno(ifp, iid));
+
+ iname = ctf_strptr(ifp, itp->ctt_name);
+ oname = ctf_strptr(ofp, otp->ctt_name);
+
+ if ((iname == NULL || oname == NULL) && (iname != oname))
+ return (B_TRUE);
+
+ /* Two anonymous names are the same */
+ if (iname == NULL && oname == NULL)
+ return (B_FALSE);
+
+ return (strcmp(iname, oname) == 0 ? B_FALSE: B_TRUE);
+}
+
+/*
+ * For floats and ints
+ */
+static int
+ctf_diff_number(ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp, ctf_id_t oid)
+{
+ ctf_encoding_t ien, den;
+
+ if (ctf_type_encoding(ifp, iid, &ien) != 0)
+ return (CTF_ERR);
+
+ if (ctf_type_encoding(ofp, oid, &den) != 0)
+ return (ctf_set_errno(ifp, iid));
+
+ if (bcmp(&ien, &den, sizeof (ctf_encoding_t)) != 0)
+ return (B_TRUE);
+
+ return (B_FALSE);
+}
+
+/*
+ * Two qualifiers are equivalent iff they point to two equivalent types.
+ */
+static int
+ctf_diff_qualifier(ctf_diff_t *cds, ctf_file_t *ifp, ctf_id_t iid,
+ ctf_file_t *ofp, ctf_id_t oid)
+{
+ ctf_id_t iref, oref;
+
+ iref = ctf_type_reference(ifp, iid);
+ if (iref == CTF_ERR)
+ return (CTF_ERR);
+
+ oref = ctf_type_reference(ofp, oid);
+ if (oref == CTF_ERR)
+ return (ctf_set_errno(ifp, ctf_errno(ofp)));
+
+ return (ctf_diff_type(cds, ifp, iref, ofp, oref));
+}
+
+/*
+ * Two arrays are the same iff they have the same type for contents, the same
+ * type for the index, and the same number of elements.
+ */
+static int
+ctf_diff_array(ctf_diff_t *cds, ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp,
+ ctf_id_t oid)
+{
+ int ret;
+ ctf_arinfo_t iar, oar;
+
+ if (ctf_array_info(ifp, iid, &iar) == CTF_ERR)
+ return (CTF_ERR);
+
+ if (ctf_array_info(ofp, oid, &oar) == CTF_ERR)
+ return (ctf_set_errno(ifp, ctf_errno(ofp)));
+
+ ret = ctf_diff_type(cds, ifp, iar.ctr_contents, ofp, oar.ctr_contents);
+ if (ret != B_FALSE)
+ return (ret);
+
+ if (iar.ctr_nelems == oar.ctr_nelems)
+ return (B_FALSE);
+
+ ret = ctf_diff_type(cds, ifp, iar.ctr_index, ofp, oar.ctr_index);
+ if (ret != B_FALSE)
+ return (ret);
+
+ return (B_TRUE);
+}
+
+/*
+ * Two function pointers are the same if the following is all true:
+ *
+ * o They have the same return type
+ * o They have the same number of arguments
+ * o The arguments are of the same type
+ * o They have the same flags
+ */
+static int
+ctf_diff_func(ctf_diff_t *cds, ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp,
+ ctf_id_t oid)
+{
+ int ret, i;
+ ctf_funcinfo_t ifunc, ofunc;
+ ctf_id_t *iids, *oids;
+
+ if (ctf_func_info_by_id(ifp, iid, &ifunc) == CTF_ERR)
+ return (CTF_ERR);
+
+ if (ctf_func_info_by_id(ofp, oid, &ofunc) == CTF_ERR)
+ return (ctf_set_errno(ifp, ctf_errno(ofp)));
+
+ if (ifunc.ctc_argc != ofunc.ctc_argc)
+ return (B_TRUE);
+
+ if (ifunc.ctc_flags != ofunc.ctc_flags)
+ return (B_TRUE);
+
+ ret = ctf_diff_type(cds, ifp, ifunc.ctc_return, ofp, ofunc.ctc_return);
+ if (ret != B_FALSE)
+ return (ret);
+
+ iids = ctf_alloc(sizeof (ctf_id_t) * ifunc.ctc_argc);
+ if (iids == NULL)
+ return (ctf_set_errno(ifp, ENOMEM));
+
+ oids = ctf_alloc(sizeof (ctf_id_t) * ifunc.ctc_argc);
+ if (oids == NULL) {
+ ctf_free(iids, sizeof (ctf_id_t) * ifunc.ctc_argc);
+ return (ctf_set_errno(ifp, ENOMEM));
+ }
+
+ if (ctf_func_args_by_id(ifp, iid, ifunc.ctc_argc, iids) == CTF_ERR) {
+ ret = CTF_ERR;
+ goto out;
+ }
+
+ if (ctf_func_args_by_id(ofp, oid, ofunc.ctc_argc, oids) == CTF_ERR) {
+ ret = ctf_set_errno(ifp, ctf_errno(ofp));
+ goto out;
+ }
+
+ ret = B_TRUE;
+ for (i = 0; i < ifunc.ctc_argc; i++) {
+ ret = ctf_diff_type(cds, ifp, iids[i], ofp, oids[i]);
+ if (ret != B_FALSE)
+ goto out;
+ }
+ ret = B_FALSE;
+
+out:
+ ctf_free(iids, sizeof (ctf_id_t) * ifunc.ctc_argc);
+ ctf_free(oids, sizeof (ctf_id_t) * ofunc.ctc_argc);
+ return (ret);
+}
+
+/*
+ * Two structures are the same if every member is identical to its corresponding
+ * type, at the same offset, and has the same name.
+ */
+static int
+ctf_diff_struct(ctf_diff_t *cds, ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp,
+ ctf_id_t oid)
+{
+ ctf_file_t *oifp;
+ const ctf_type_t *itp, *otp;
+ ssize_t isize, iincr, osize, oincr;
+ const ctf_member_t *imp, *omp;
+ const ctf_lmember_t *ilmp, *olmp;
+ int n;
+
+ oifp = ifp;
+
+ if ((itp = ctf_lookup_by_id(&ifp, iid)) == NULL)
+ return (CTF_ERR);
+
+ if ((otp = ctf_lookup_by_id(&ofp, oid)) == NULL)
+ return (ctf_set_errno(oifp, ctf_errno(ofp)));
+
+ if (LCTF_INFO_VLEN(ifp, itp->ctt_info) !=
+ LCTF_INFO_VLEN(ofp, otp->ctt_info))
+ return (B_TRUE);
+
+ (void) ctf_get_ctt_size(ifp, itp, &isize, &iincr);
+ (void) ctf_get_ctt_size(ofp, otp, &osize, &oincr);
+
+ if (ifp->ctf_version == CTF_VERSION_1 || isize < CTF_LSTRUCT_THRESH) {
+ imp = (const ctf_member_t *)((uintptr_t)itp + iincr);
+ ilmp = NULL;
+ } else {
+ imp = NULL;
+ ilmp = (const ctf_lmember_t *)((uintptr_t)itp + iincr);
+ }
+
+ if (ofp->ctf_version == CTF_VERSION_1 || osize < CTF_LSTRUCT_THRESH) {
+ omp = (const ctf_member_t *)((uintptr_t)otp + oincr);
+ olmp = NULL;
+ } else {
+ omp = NULL;
+ olmp = (const ctf_lmember_t *)((uintptr_t)otp + oincr);
+ }
+
+ for (n = LCTF_INFO_VLEN(ifp, itp->ctt_info); n != 0; n--) {
+ const char *iname, *oname;
+ ulong_t ioff, ooff;
+ ctf_id_t itype, otype;
+ int ret;
+
+ if (imp != NULL) {
+ iname = ctf_strptr(ifp, imp->ctm_name);
+ ioff = imp->ctm_offset;
+ itype = imp->ctm_type;
+ } else {
+ iname = ctf_strptr(ifp, ilmp->ctlm_name);
+ ioff = CTF_LMEM_OFFSET(ilmp);
+ itype = ilmp->ctlm_type;
+ }
+
+ if (omp != NULL) {
+ oname = ctf_strptr(ofp, omp->ctm_name);
+ ooff = omp->ctm_offset;
+ otype = omp->ctm_type;
+ } else {
+ oname = ctf_strptr(ofp, olmp->ctlm_name);
+ ooff = CTF_LMEM_OFFSET(olmp);
+ otype = olmp->ctlm_type;
+ }
+
+ if (ioff != ooff) {
+ return (B_TRUE);
+ }
+ if (strcmp(iname, oname) != 0) {
+ return (B_TRUE);
+ }
+ ret = ctf_diff_type(cds, ifp, itype, ofp, otype);
+ if (ret != B_FALSE)
+ return (ret);
+
+ /* Advance our pointers */
+ if (imp != NULL)
+ imp++;
+ if (ilmp != NULL)
+ ilmp++;
+ if (omp != NULL)
+ omp++;
+ if (olmp != NULL)
+ olmp++;
+ }
+
+ return (B_FALSE);
+}
+
+/*
+ * Two unions are the same if they have the same set of members. This is similar
+ * to, but slightly different from a struct. The offsets of members don't
+ * matter. However, their is no guarantee of ordering so we have to fall back to
+ * doing an O(N^2) scan.
+ */
+typedef struct ctf_diff_union_member {
+ ctf_diff_t *cdum_cds;
+ ctf_file_t *cdum_fp;
+ ctf_file_t *cdum_iterfp;
+ const char *cdum_name;
+ ctf_id_t cdum_type;
+ int cdum_ret;
+} ctf_diff_union_member_t;
+
+typedef struct ctf_diff_union_fp {
+ ctf_diff_t *cduf_cds;
+ ctf_file_t *cduf_curfp;
+ ctf_file_t *cduf_altfp;
+ ctf_id_t cduf_type;
+ int cduf_ret;
+} ctf_diff_union_fp_t;
+
+/* ARGSUSED */
+static int
+ctf_diff_union_check_member(const char *name, ctf_id_t id, ulong_t off,
+ void *arg)
+{
+ int ret;
+ ctf_diff_union_member_t *cdump = arg;
+
+ if (strcmp(name, cdump->cdum_name) != 0)
+ return (0);
+
+ ret = ctf_diff_type(cdump->cdum_cds, cdump->cdum_fp, cdump->cdum_type,
+ cdump->cdum_iterfp, id);
+ if (ret == CTF_ERR) {
+ cdump->cdum_ret = CTF_ERR;
+ return (1);
+ }
+
+ if (ret == B_FALSE) {
+ cdump->cdum_ret = B_FALSE;
+ /* Return non-zero to stop iteration as we have a match */
+ return (1);
+ }
+
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+ctf_diff_union_check_fp(const char *name, ctf_id_t id, ulong_t off, void *arg)
+{
+ int ret;
+ ctf_diff_union_member_t cdum;
+ ctf_diff_union_fp_t *cdufp = arg;
+
+ cdum.cdum_cds = cdufp->cduf_cds;
+ cdum.cdum_fp = cdufp->cduf_curfp;
+ cdum.cdum_iterfp = cdufp->cduf_altfp;
+ cdum.cdum_name = name;
+ cdum.cdum_type = id;
+ cdum.cdum_ret = B_TRUE;
+
+ ret = ctf_member_iter(cdum.cdum_iterfp, cdufp->cduf_type,
+ ctf_diff_union_check_member, &cdum);
+ if (ret == 0 || cdum.cdum_ret == CTF_ERR) {
+ /* No match found or error, terminate now */
+ cdufp->cduf_ret = cdum.cdum_ret;
+ return (1);
+ } else if (ret == CTF_ERR) {
+ (void) ctf_set_errno(cdum.cdum_fp, ctf_errno(cdum.cdum_iterfp));
+ cdufp->cduf_ret = CTF_ERR;
+ return (1);
+ } else {
+ ASSERT(cdum.cdum_ret == B_FALSE);
+ cdufp->cduf_ret = cdum.cdum_ret;
+ return (0);
+ }
+}
+
+static int
+ctf_diff_union(ctf_diff_t *cds, ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp,
+ ctf_id_t oid)
+{
+ ctf_file_t *oifp;
+ const ctf_type_t *itp, *otp;
+ ctf_diff_union_fp_t cduf;
+ int ret;
+
+ oifp = ifp;
+ if ((itp = ctf_lookup_by_id(&ifp, iid)) == NULL)
+ return (CTF_ERR);
+ if ((otp = ctf_lookup_by_id(&ofp, oid)) == NULL)
+ return (ctf_set_errno(oifp, ctf_errno(ofp)));
+
+ if (LCTF_INFO_VLEN(ifp, itp->ctt_info) !=
+ LCTF_INFO_VLEN(ofp, otp->ctt_info))
+ return (B_TRUE);
+
+ cduf.cduf_cds = cds;
+ cduf.cduf_curfp = ifp;
+ cduf.cduf_altfp = ofp;
+ cduf.cduf_type = oid;
+ cduf.cduf_ret = B_TRUE;
+ ret = ctf_member_iter(ifp, iid, ctf_diff_union_check_fp, &cduf);
+ if (ret != CTF_ERR)
+ ret = cduf.cduf_ret;
+
+ return (ret);
+}
+
+/*
+ * Two enums are equivalent if they share the same underlying type and they have
+ * the same set of members.
+ */
+static int
+ctf_diff_enum(ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp, ctf_id_t oid)
+{
+ ctf_file_t *oifp;
+ const ctf_type_t *itp, *otp;
+ ssize_t iincr, oincr;
+ const ctf_enum_t *iep, *oep;
+ int n;
+
+ oifp = ifp;
+ if ((itp = ctf_lookup_by_id(&ifp, iid)) == NULL)
+ return (CTF_ERR);
+ if ((otp = ctf_lookup_by_id(&ofp, oid)) == NULL)
+ return (ctf_set_errno(oifp, ctf_errno(ofp)));
+
+ if (LCTF_INFO_VLEN(ifp, itp->ctt_info) !=
+ LCTF_INFO_VLEN(ofp, otp->ctt_info))
+ return (B_TRUE);
+
+ (void) ctf_get_ctt_size(ifp, itp, NULL, &iincr);
+ (void) ctf_get_ctt_size(ofp, otp, NULL, &oincr);
+ iep = (const ctf_enum_t *)((uintptr_t)itp + iincr);
+ oep = (const ctf_enum_t *)((uintptr_t)otp + oincr);
+
+ for (n = LCTF_INFO_VLEN(ifp, itp->ctt_info); n != 0;
+ n--, iep++, oep++) {
+ if (strcmp(ctf_strptr(ifp, iep->cte_name),
+ ctf_strptr(ofp, oep->cte_name)) != 0)
+ return (B_TRUE);
+
+ if (iep->cte_value != oep->cte_value)
+ return (B_TRUE);
+ }
+
+ return (B_FALSE);
+}
+
+/*
+ * Two forwards are equivalent in one of two cases. If both are forwards, than
+ * they are the same. Otherwise, they're equivalent if one is a struct or union
+ * and the other is a forward.
+ */
+static int
+ctf_diff_forward(ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp, ctf_id_t oid)
+{
+ int ikind, okind;
+
+ ikind = ctf_type_kind(ifp, iid);
+ okind = ctf_type_kind(ofp, oid);
+
+ if (ikind == okind) {
+ ASSERT(ikind == CTF_K_FORWARD);
+ return (B_FALSE);
+ } else if (ikind == CTF_K_FORWARD) {
+ return (okind != CTF_K_UNION && okind != CTF_K_STRUCT);
+ } else {
+ return (ikind != CTF_K_UNION && ikind != CTF_K_STRUCT);
+ }
+}
+
+/*
+ * Are two types equivalent?
+ */
+int
+ctf_diff_type(ctf_diff_t *cds, ctf_file_t *ifp, ctf_id_t iid, ctf_file_t *ofp,
+ ctf_id_t oid)
+{
+ int ret, ikind, okind;
+ ctf_ihelem_t *lookup, *fv, *rv;
+
+ /* Do a quick short circuit */
+ if (ifp == ofp && iid == oid)
+ return (B_FALSE);
+
+ /*
+ * Check if it's something we've already encountered in a forward
+ * reference or forward negative table.
+ */
+ if ((lookup = ctf_idhash_lookup(&cds->cds_forward, iid)) != NULL) {
+ if (lookup->ih_value == oid)
+ return (B_FALSE);
+ else
+ return (B_TRUE);
+ }
+
+ if (ctf_idhash_lookup(&cds->cds_forward, iid) != NULL) {
+ return (B_TRUE);
+ }
+
+ fv = ctf_idhash_lookup(&cds->cds_f_visited, iid);
+ rv = ctf_idhash_lookup(&cds->cds_r_visited, oid);
+ if (fv != NULL && rv != NULL)
+ return (fv->ih_value != rv->ih_value);
+ else if (fv != NULL || rv != NULL)
+ return (B_TRUE);
+
+ ikind = ctf_type_kind(ifp, iid);
+ okind = ctf_type_kind(ofp, oid);
+
+ /* Check names */
+ if ((ret = ctf_diff_name(ifp, iid, ofp, oid)) != B_FALSE) {
+ if (ikind != okind || ikind != CTF_K_INTEGER ||
+ (cds->cds_flags & CTF_DIFF_F_IGNORE_INTNAMES) == 0)
+ return (ret);
+ }
+
+ if (ikind != okind) {
+ if (ikind == CTF_K_FORWARD || okind == CTF_K_FORWARD)
+ return (ctf_diff_forward(ifp, iid, ofp, oid));
+ else
+ return (B_TRUE);
+ }
+
+ switch (ikind) {
+ case CTF_K_INTEGER:
+ case CTF_K_FLOAT:
+ ret = ctf_diff_number(ifp, iid, ofp, oid);
+ break;
+ case CTF_K_ARRAY:
+ ret = ctf_diff_array(cds, ifp, iid, ofp, oid);
+ break;
+ case CTF_K_FUNCTION:
+ ret = ctf_diff_func(cds, ifp, iid, ofp, oid);
+ break;
+ case CTF_K_STRUCT:
+ VERIFY(ctf_idhash_insert(&cds->cds_f_visited, iid,
+ cds->cds_visitid) == 0);
+ VERIFY(ctf_idhash_insert(&cds->cds_r_visited, oid,
+ cds->cds_visitid) == 0);
+ cds->cds_visitid++;
+ ret = ctf_diff_struct(cds, ifp, iid, ofp, oid);
+ break;
+ case CTF_K_UNION:
+ VERIFY(ctf_idhash_insert(&cds->cds_f_visited, iid,
+ cds->cds_visitid) == 0);
+ VERIFY(ctf_idhash_insert(&cds->cds_r_visited, oid,
+ cds->cds_visitid) == 0);
+ cds->cds_visitid++;
+ ret = ctf_diff_union(cds, ifp, iid, ofp, oid);
+ break;
+ case CTF_K_ENUM:
+ ret = ctf_diff_enum(ifp, iid, ofp, oid);
+ break;
+ case CTF_K_FORWARD:
+ ret = ctf_diff_forward(ifp, iid, ofp, oid);
+ break;
+ case CTF_K_POINTER:
+ case CTF_K_TYPEDEF:
+ case CTF_K_VOLATILE:
+ case CTF_K_CONST:
+ case CTF_K_RESTRICT:
+ ret = ctf_diff_qualifier(cds, ifp, iid, ofp, oid);
+ break;
+ case CTF_K_UNKNOWN:
+ /*
+ * The current CTF tools use CTF_K_UNKNOWN as a padding type. We
+ * always declare two instances of CTF_K_UNKNOWN as different,
+ * even though this leads to additional diff noise.
+ */
+ ret = B_TRUE;
+ break;
+ default:
+ abort();
+ }
+
+ return (ret);
+}
+
+/*
+ * Walk every type in the first container and try to find a match in the second.
+ * If there is a match, then update both the forward and reverse mapping tables.
+ */
+static int
+ctf_diff_pass1(ctf_diff_t *cds)
+{
+ int i, j, diff;
+ int istart, iend, jstart, jend;
+
+ if (cds->cds_ifp->ctf_flags & LCTF_CHILD) {
+ istart = 0x8001;
+ iend = cds->cds_ifp->ctf_typemax + 0x8000;
+ } else {
+ istart = 1;
+ iend = cds->cds_ifp->ctf_typemax;
+ }
+
+ if (cds->cds_ofp->ctf_flags & LCTF_CHILD) {
+ jstart = 0x8001;
+ jend = cds->cds_ofp->ctf_typemax + 0x8000;
+ } else {
+ jstart = 1;
+ jend = cds->cds_ofp->ctf_typemax;
+ }
+
+ for (i = istart; i <= iend; i++) {
+ diff = B_TRUE;
+ for (j = jstart; j <= jend; j++) {
+ cds->cds_visitid = 1;
+ ctf_idhash_clear(&cds->cds_f_visited);
+ ctf_idhash_clear(&cds->cds_r_visited);
+
+ diff = ctf_diff_type(cds, cds->cds_ifp, i,
+ cds->cds_ofp, j);
+ if (diff == CTF_ERR)
+ return (CTF_ERR);
+
+ /* Found a hit, update the tables */
+ if (diff == B_FALSE) {
+ VERIFY(ctf_idhash_lookup(&cds->cds_forward,
+ i) == NULL);
+ VERIFY(ctf_idhash_insert(&cds->cds_forward,
+ i, j) == 0);
+ if (ctf_idhash_lookup(&cds->cds_reverse, j) ==
+ NULL) {
+ VERIFY(ctf_idhash_lookup(
+ &cds->cds_reverse, j) == NULL);
+ VERIFY(ctf_idhash_insert(
+ &cds->cds_reverse, j, i) == 0);
+ }
+ break;
+ }
+ }
+
+ /* Call the callback at this point */
+ if (diff == B_TRUE) {
+ VERIFY(ctf_idhash_insert(&cds->cds_fneg, i, 1) == 0);
+ cds->cds_func(cds->cds_ifp, i, B_FALSE, NULL, CTF_ERR,
+ cds->cds_arg);
+ } else {
+ cds->cds_func(cds->cds_ifp, i, B_TRUE, cds->cds_ofp, j,
+ cds->cds_arg);
+ }
+ }
+
+ return (0);
+}
+
+/*
+ * Now we need to walk the second container and emit anything that we didn't
+ * find as common in the first pass.
+ */
+static int
+ctf_diff_pass2(ctf_diff_t *cds)
+{
+ int i;
+
+ for (i = 1; i <= cds->cds_ofp->ctf_typemax; i++) {
+ if (ctf_idhash_lookup(&cds->cds_reverse, i) != NULL)
+ continue;
+ cds->cds_func(cds->cds_ofp, i, B_FALSE, NULL, CTF_ERR,
+ cds->cds_arg);
+ }
+
+ return (0);
+}
+
+int
+ctf_diff_init(ctf_file_t *ifp, ctf_file_t *ofp, ctf_diff_t **cdsp)
+{
+ int ret;
+ ctf_diff_t *cds;
+
+ cds = ctf_alloc(sizeof (ctf_diff_t));
+ if (cds == NULL)
+ return (ctf_set_errno(ifp, ENOMEM));
+
+ bzero(cds, sizeof (ctf_diff_t));
+ cds->cds_ifp = ifp;
+ cds->cds_ofp = ofp;
+ ret = ctf_idhash_create(&cds->cds_forward, ifp->ctf_typemax);
+ if (ret != 0) {
+ ctf_free(cds, sizeof (ctf_diff_t));
+ return (ctf_set_errno(ifp, ret));
+ }
+ ret = ctf_idhash_create(&cds->cds_reverse, ofp->ctf_typemax);
+ if (ret != 0) {
+ ctf_idhash_destroy(&cds->cds_forward);
+ ctf_free(cds, sizeof (ctf_diff_t));
+ return (ctf_set_errno(ifp, ret));
+ }
+ ret = ctf_idhash_create(&cds->cds_f_visited, ifp->ctf_typemax);
+ if (ret != 0) {
+ ctf_idhash_destroy(&cds->cds_reverse);
+ ctf_idhash_destroy(&cds->cds_forward);
+ ctf_free(cds, sizeof (ctf_diff_t));
+ return (ctf_set_errno(ifp, ret));
+ }
+ ret = ctf_idhash_create(&cds->cds_r_visited, ofp->ctf_typemax);
+ if (ret != 0) {
+ ctf_idhash_destroy(&cds->cds_f_visited);
+ ctf_idhash_destroy(&cds->cds_reverse);
+ ctf_idhash_destroy(&cds->cds_forward);
+ ctf_free(cds, sizeof (ctf_diff_t));
+ return (ctf_set_errno(ifp, ret));
+ }
+ ret = ctf_idhash_create(&cds->cds_fneg, ifp->ctf_typemax);
+ if (ret != 0) {
+ ctf_idhash_destroy(&cds->cds_r_visited);
+ ctf_idhash_destroy(&cds->cds_f_visited);
+ ctf_idhash_destroy(&cds->cds_reverse);
+ ctf_idhash_destroy(&cds->cds_forward);
+ ctf_free(cds, sizeof (ctf_diff_t));
+ return (ctf_set_errno(ifp, ret));
+ }
+
+ cds->cds_ifp->ctf_refcnt++;
+ cds->cds_ofp->ctf_refcnt++;
+ *cdsp = cds;
+ return (0);
+}
+
+int
+ctf_diff_types(ctf_diff_t *cds, ctf_diff_type_f cb, void *arg)
+{
+ int ret;
+
+ cds->cds_func = cb;
+ cds->cds_arg = arg;
+
+ /*
+ * For the moment clear all idhashes and rerun this phase. Ideally we
+ * should reuse this, but we can save that for when we add things like
+ * taking the diff of the objects and the like.
+ */
+ ctf_idhash_clear(&cds->cds_forward);
+ ctf_idhash_clear(&cds->cds_reverse);
+ ctf_idhash_clear(&cds->cds_fneg);
+ ctf_idhash_clear(&cds->cds_f_visited);
+ ctf_idhash_clear(&cds->cds_r_visited);
+
+ ret = ctf_diff_pass1(cds);
+ if (ret == 0)
+ ret = ctf_diff_pass2(cds);
+
+ cds->cds_func = NULL;
+ cds->cds_arg = NULL;
+ return (ret);
+}
+
+void
+ctf_diff_fini(ctf_diff_t *cds)
+{
+ cds->cds_ifp->ctf_refcnt--;
+ cds->cds_ofp->ctf_refcnt--;
+
+ ctf_idhash_destroy(&cds->cds_fneg);
+ ctf_idhash_destroy(&cds->cds_r_visited);
+ ctf_idhash_destroy(&cds->cds_f_visited);
+ ctf_idhash_destroy(&cds->cds_reverse);
+ ctf_idhash_destroy(&cds->cds_forward);
+ ctf_free(cds, sizeof (ctf_diff_t));
+}
+
+uint_t
+ctf_diff_getflags(ctf_diff_t *cds)
+{
+ return (cds->cds_flags);
+}
+
+int
+ctf_diff_setflags(ctf_diff_t *cds, uint_t flags)
+{
+ if ((flags & ~CTF_DIFF_F_MASK) != 0)
+ return (ctf_set_errno(cds->cds_ifp, EINVAL));
+
+ cds->cds_flags = flags;
+ return (0);
+}
diff --git a/usr/src/lib/libctf/common/libctf.h b/usr/src/lib/libctf/common/libctf.h
index 3fd69318de..07601b4ee4 100644
--- a/usr/src/lib/libctf/common/libctf.h
+++ b/usr/src/lib/libctf/common/libctf.h
@@ -23,6 +23,9 @@
* Copyright 2001-2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2014, Joyent, Inc. All rights reserved.
+ */
/*
* This header file defines the interfaces available from the CTF debugger
@@ -40,8 +43,6 @@
#ifndef _LIBCTF_H
#define _LIBCTF_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/ctf_api.h>
#ifdef __cplusplus
@@ -53,6 +54,21 @@ extern "C" {
*/
extern int _libctf_debug;
+typedef enum ctf_diff_flag {
+ CTF_DIFF_F_IGNORE_INTNAMES = 0x01,
+ CTF_DIFF_F_MASK = 0x01
+} ctf_diff_flag_t;
+
+typedef struct ctf_diff ctf_diff_t;
+typedef void (*ctf_diff_type_f)(ctf_file_t *, ctf_id_t, boolean_t, ctf_file_t *,
+ ctf_id_t, void *);
+
+extern int ctf_diff_init(ctf_file_t *, ctf_file_t *, ctf_diff_t **);
+extern uint_t ctf_diff_getflags(ctf_diff_t *);
+extern int ctf_diff_setflags(ctf_diff_t *, uint_t);
+extern int ctf_diff_types(ctf_diff_t *, ctf_diff_type_f, void *);
+extern void ctf_diff_fini(ctf_diff_t *);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/libctf/common/mapfile-vers b/usr/src/lib/libctf/common/mapfile-vers
index 5573e8db25..d09b88fd01 100644
--- a/usr/src/lib/libctf/common/mapfile-vers
+++ b/usr/src/lib/libctf/common/mapfile-vers
@@ -65,9 +65,26 @@ SYMBOL_VERSION SUNWprivate_1.2 {
ctf_add_volatile;
ctf_create;
ctf_delete_type;
+ ctf_diff_init;
+ ctf_diff_fini;
+ ctf_diff_getflags;
+ ctf_diff_setflags;
+ ctf_diff_types;
ctf_discard;
ctf_dup;
ctf_enum_value;
+ ctf_func_args_by_id;
+ ctf_func_info_by_id;
+ ctf_idhash_clear;
+ ctf_idhash_create;
+ ctf_idhash_define;
+ ctf_idhash_insert;
+ ctf_idhash_iter;
+ ctf_idhash_iter_init;
+ ctf_idhash_iter_fini;
+ ctf_idhash_lookup;
+ ctf_idhash_size;
+ ctf_idhash_destroy;
ctf_label_info;
ctf_label_iter;
ctf_label_topmost;
diff --git a/usr/src/lib/libvnd/Makefile b/usr/src/lib/libvnd/Makefile
index 0b3f923806..1352adb8e4 100644
--- a/usr/src/lib/libvnd/Makefile
+++ b/usr/src/lib/libvnd/Makefile
@@ -26,13 +26,21 @@ clobber := TARGET = clobber
install := TARGET = install
lint := TARGET = lint
+TYPECHECK_LIB = libvnd.so.1
+TYPELIST = \
+ vnd_ioc_attach_t \
+ vnd_ioc_link_t \
+ vnd_ioc_unlink_t \
+ vnd_ioc_buf_t \
+ vnd_ioc_info_t
+
.KEEP_STATE:
all clean clobber install lint: $(SUBDIRS)
install_h: $(ROOTHDRS)
-check: $(CHECKHDRS)
+check: $(CHECKHDRS) $(TYPECHECK)
$(SUBDIRS): FRC
@cd $@; pwd; $(MAKE) $(TARGET)
diff --git a/usr/src/tools/ctf/Makefile b/usr/src/tools/ctf/Makefile
index 0746c4943f..675c16aa84 100644
--- a/usr/src/tools/ctf/Makefile
+++ b/usr/src/tools/ctf/Makefile
@@ -26,7 +26,7 @@
include ../Makefile.tools
-SUBDIRS = cvt dump stabs scripts ctfstrip
+SUBDIRS = cvt dump stabs scripts ctfstrip libctf .WAIT ctfdiff
.PARALLEL: $(SUBDIRS)
diff --git a/usr/src/tools/ctf/Makefile.ctf b/usr/src/tools/ctf/Makefile.ctf
index 7c5b041746..0cf32bf1bc 100644
--- a/usr/src/tools/ctf/Makefile.ctf
+++ b/usr/src/tools/ctf/Makefile.ctf
@@ -41,6 +41,7 @@ HDRDIRS= \
-I$(SRC) \
-I/usr/include \
-I$(SRC)/uts/common \
+ -I$(SRC)/common/ctf \
-I$(NATIVE_ADJUNCT)/include
CPPFLAGS += $(HDRDIRS)
diff --git a/usr/src/tools/ctf/common/ctf_headers.h b/usr/src/tools/ctf/common/ctf_headers.h
index 268ae79077..453c6450ed 100644
--- a/usr/src/tools/ctf/common/ctf_headers.h
+++ b/usr/src/tools/ctf/common/ctf_headers.h
@@ -65,6 +65,7 @@
#include <uts/common/sys/ctf.h>
#include <uts/common/sys/ctf_api.h>
+#include <common/ctf/ctf_impl.h>
#include <lib/libctf/common/libctf.h>
/*
diff --git a/usr/src/tools/ctf/ctfdiff/Makefile b/usr/src/tools/ctf/ctfdiff/Makefile
new file mode 100644
index 0000000000..07fadc5f8f
--- /dev/null
+++ b/usr/src/tools/ctf/ctfdiff/Makefile
@@ -0,0 +1,44 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+
+include ../../Makefile.tools
+
+SUBDIRS = $(MACH)
+
+all := TARGET= all
+install := TARGET= install
+clean := TARGET= clean
+clobber := TARGET= clobber
+lint := TARGET= lint
+
+.KEEP_STATE:
+
+install all clean clobber lint: $(SUBDIRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
diff --git a/usr/src/tools/ctf/ctfdiff/Makefile.com b/usr/src/tools/ctf/ctfdiff/Makefile.com
new file mode 100644
index 0000000000..3c5e19fb6e
--- /dev/null
+++ b/usr/src/tools/ctf/ctfdiff/Makefile.com
@@ -0,0 +1,44 @@
+#
+# 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.
+#
+
+PROG = ctfdiff
+SRCS = ctfdiff.c
+
+include ../../Makefile.ctf
+
+CFLAGS += $(CCVERBOSE)
+LDLIBS += -lctf
+
+LDFLAGS = \
+ -L$(ROOTONBLDLIBMACH) \
+ '-R$$ORIGIN/../../lib/$(MACH)' \
+
+CPPFLAGS += -include ../../common/ctf_headers.h
+
+OBJS = $(SRCS:%.c=%.o)
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+ $(LINK.c) $(OBJS) -o $@ $(LDLIBS)
+ $(POST_PROCESS)
+
+%.o: $(SRC)/cmd/ctfdiff/%.c
+ $(COMPILE.c) $<
+
+$(ROOTONBLDMACHPROG): $(PROG)
+
+install: $(ROOTONBLDMACHPROG)
+
+clean:
+ $(RM) $(OBJS) $(LINTFILES)
+
+include $(SRC)/tools/Makefile.targ
diff --git a/usr/src/tools/ctf/ctfdiff/i386/Makefile b/usr/src/tools/ctf/ctfdiff/i386/Makefile
new file mode 100644
index 0000000000..cd5462bee3
--- /dev/null
+++ b/usr/src/tools/ctf/ctfdiff/i386/Makefile
@@ -0,0 +1,27 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+
+include ../Makefile.com
diff --git a/usr/src/tools/ctf/ctfdiff/sparc/Makefile b/usr/src/tools/ctf/ctfdiff/sparc/Makefile
new file mode 100644
index 0000000000..cd5462bee3
--- /dev/null
+++ b/usr/src/tools/ctf/ctfdiff/sparc/Makefile
@@ -0,0 +1,27 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+
+include ../Makefile.com
diff --git a/usr/src/tools/ctf/libctf/Makefile b/usr/src/tools/ctf/libctf/Makefile
new file mode 100644
index 0000000000..5e9236c43d
--- /dev/null
+++ b/usr/src/tools/ctf/libctf/Makefile
@@ -0,0 +1,46 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../../Makefile.tools
+
+HDRS = libctf.h
+HDRDIR = common
+
+SUBDIRS = $(MACH)
+
+all := TARGET = all
+clean := TARGET = clean
+clobber := TARGET = clobber
+install := TARGET = install
+lint := TARGET = lint
+
+.KEEP_STATE:
+
+all clean clobber install lint: $(SUBDIRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
diff --git a/usr/src/tools/ctf/libctf/Makefile.com b/usr/src/tools/ctf/libctf/Makefile.com
new file mode 100644
index 0000000000..22e8e82318
--- /dev/null
+++ b/usr/src/tools/ctf/libctf/Makefile.com
@@ -0,0 +1,42 @@
+#
+# 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.
+#
+
+include $(SRC)/lib/libctf/Makefile.shared.com
+include ../../Makefile.ctf
+
+CPPFLAGS += -include ../../common/ctf_headers.h -DCTF_OLD_VERSIONS
+LDLIBS += -lc
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+install: all $(ROOTONBLDLIBMACH)/libctf.so.1 $(ROOTONBLDLIBMACH)/libctf.so
+
+$(ROOTONBLDLIBMACH)/%: %
+ $(INS.file)
+
+$(ROOTONBLDLIBMACH)/$(LIBLINKS): $(ROOTONBLDLIBMACH)/$(LIBLINKS)$(VERS)
+ $(INS.liblink)
+
+#
+# Just like with libdwarf, we can't actually add ctf to ourselves,
+# because we're part of the tools for creating CTF.
+#
+$(DYNLIB) := CTFMERGE_POST= :
+CTFCONVERT_O= :
+
+include $(SRC)/lib/Makefile.targ
+include $(SRC)/lib/libctf/Makefile.shared.targ
diff --git a/usr/src/tools/ctf/libctf/i386/Makefile b/usr/src/tools/ctf/libctf/i386/Makefile
new file mode 100644
index 0000000000..fff958ac6e
--- /dev/null
+++ b/usr/src/tools/ctf/libctf/i386/Makefile
@@ -0,0 +1,8 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../Makefile.com
+
+all: $(LIBS)
diff --git a/usr/src/tools/ctf/libctf/sparc/Makefile b/usr/src/tools/ctf/libctf/sparc/Makefile
new file mode 100644
index 0000000000..fff958ac6e
--- /dev/null
+++ b/usr/src/tools/ctf/libctf/sparc/Makefile
@@ -0,0 +1,8 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../Makefile.com
+
+all: $(LIBS)
diff --git a/usr/src/uts/common/sys/ctf_api.h b/usr/src/uts/common/sys/ctf_api.h
index 04d73c3181..ab648d5489 100644
--- a/usr/src/uts/common/sys/ctf_api.h
+++ b/usr/src/uts/common/sys/ctf_api.h
@@ -169,7 +169,9 @@ extern const char *ctf_errmsg(int);
extern int ctf_version(int);
extern int ctf_func_info(ctf_file_t *, ulong_t, ctf_funcinfo_t *);
+extern int ctf_func_info_by_id(ctf_file_t *, ctf_id_t, ctf_funcinfo_t *);
extern int ctf_func_args(ctf_file_t *, ulong_t, uint_t, ctf_id_t *);
+extern int ctf_func_args_by_id(ctf_file_t *, ctf_id_t, uint_t, ctf_id_t *);
extern ctf_id_t ctf_lookup_by_name(ctf_file_t *, const char *);
extern ctf_id_t ctf_lookup_by_symbol(ctf_file_t *, ulong_t);
@@ -240,6 +242,34 @@ extern ctf_file_t *ctf_modopen(struct module *, int *);
#endif
+typedef struct ctf_ihelem {
+ ushort_t ih_type; /* type ID number */
+ ushort_t ih_value; /* type ID number in a different fp */
+ ushort_t ih_next; /* index of next element in hash chain */
+} ctf_ihelem_t;
+
+typedef struct ctf_idhash {
+ ushort_t *ih_buckets; /* hash bucket array (chain indices) */
+ ctf_ihelem_t *ih_chains; /* hash chains buffer */
+ ushort_t ih_nbuckets; /* number of elements in bucket array */
+ ushort_t ih_nelems; /* number of elements in hash table */
+ uint_t ih_free; /* index of next free hash element */
+} ctf_idhash_t;
+
+extern int ctf_idhash_create(ctf_idhash_t *, ulong_t);
+extern void ctf_idhash_clear(ctf_idhash_t *);
+extern int ctf_idhash_define(ctf_idhash_t *, ushort_t, ushort_t);
+extern int ctf_idhash_insert(ctf_idhash_t *, ushort_t, ushort_t);
+extern ctf_ihelem_t *ctf_idhash_lookup(ctf_idhash_t *, ushort_t);
+extern uint_t ctf_idhash_size(const ctf_idhash_t *);
+extern void ctf_idhash_destroy(ctf_idhash_t *);
+
+typedef struct ctf_idhash_iter ctf_idhash_iter_t;
+extern int ctf_idhash_iter_init(ctf_idhash_t *, ctf_idhash_iter_t **);
+extern const ctf_ihelem_t *ctf_idhash_iter(ctf_idhash_t *,
+ ctf_idhash_iter_t *);
+extern void ctf_idhash_iter_fini(ctf_idhash_t *, ctf_idhash_iter_t *);
+
#ifdef __cplusplus
}
#endif