diff options
author | Robert Mustacchi <rm@joyent.com> | 2014-07-12 00:48:08 +0000 |
---|---|---|
committer | Robert Mustacchi <rm@joyent.com> | 2014-07-18 22:22:02 +0000 |
commit | 4bd0c2b79d9b19403df4764e4b7941b29abe4a80 (patch) | |
tree | 2780b304153df871a1dcc9ec991ae4ff57211d7f | |
parent | 1fba5429ccf7095093d8035f56380cf7b125f0f2 (diff) | |
download | illumos-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>
36 files changed, 1896 insertions, 47 deletions
@@ -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 |