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 /usr/src | |
| 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>
Diffstat (limited to 'usr/src')
35 files changed, 1894 insertions, 47 deletions
| 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 | 
