summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Levon <john.levon@joyent.com>2019-09-04 06:01:25 -0700
committerJohn Levon <john.levon@joyent.com>2019-09-12 04:40:11 -0700
commitce115d25b7c5f8cff5a9444c4d0d1ea9d31c2056 (patch)
tree7a01d000c16bb1782f1bf2db41ad8ae5136f9057
parent8eb8717cc9dc99bdd784b74c994bea7ef5e60f92 (diff)
downloadillumos-joyent-ce115d25b7c5f8cff5a9444c4d0d1ea9d31c2056.tar.gz
11657 Remove old ctf tools
Reviewed by: Robert Mustacchi <rm@joyent.com> Approved by: Dan McDonald <danmcd@joyent.com>
-rw-r--r--usr/src/Makefile.master9
-rw-r--r--usr/src/cmd/ctfconvert/ctfconvert.c28
-rw-r--r--usr/src/cmd/ctfmerge/ctfmerge.c25
-rw-r--r--usr/src/tools/ctf/Makefile6
-rw-r--r--usr/src/tools/ctf/cvt/Makefile45
-rw-r--r--usr/src/tools/ctf/cvt/Makefile.com91
-rw-r--r--usr/src/tools/ctf/cvt/Makefile.targ75
-rw-r--r--usr/src/tools/ctf/cvt/alist.c205
-rw-r--r--usr/src/tools/ctf/cvt/alist.h56
-rw-r--r--usr/src/tools/ctf/cvt/altexec.c45
-rw-r--r--usr/src/tools/ctf/cvt/barrier.c78
-rw-r--r--usr/src/tools/ctf/cvt/barrier.h57
-rw-r--r--usr/src/tools/ctf/cvt/compare.c92
-rw-r--r--usr/src/tools/ctf/cvt/ctf.c1282
-rw-r--r--usr/src/tools/ctf/cvt/ctfconvert.c255
-rw-r--r--usr/src/tools/ctf/cvt/ctfmerge.c1004
-rw-r--r--usr/src/tools/ctf/cvt/ctfmerge.h90
-rw-r--r--usr/src/tools/ctf/cvt/ctftools.h452
-rw-r--r--usr/src/tools/ctf/cvt/dwarf.c2027
-rw-r--r--usr/src/tools/ctf/cvt/fifo.c153
-rw-r--r--usr/src/tools/ctf/cvt/fifo.h54
-rw-r--r--usr/src/tools/ctf/cvt/fixup_tdescs.c277
-rw-r--r--usr/src/tools/ctf/cvt/hash.c287
-rw-r--r--usr/src/tools/ctf/cvt/hash.h59
-rw-r--r--usr/src/tools/ctf/cvt/i386/Makefile29
-rw-r--r--usr/src/tools/ctf/cvt/iidesc.c196
-rw-r--r--usr/src/tools/ctf/cvt/input.c418
-rw-r--r--usr/src/tools/ctf/cvt/merge.c1140
-rw-r--r--usr/src/tools/ctf/cvt/output.c713
-rw-r--r--usr/src/tools/ctf/cvt/sparc/Makefile29
-rw-r--r--usr/src/tools/ctf/cvt/st_parse.c1214
-rw-r--r--usr/src/tools/ctf/cvt/stabs.c382
-rw-r--r--usr/src/tools/ctf/cvt/stack.c112
-rw-r--r--usr/src/tools/ctf/cvt/stack.h53
-rw-r--r--usr/src/tools/ctf/cvt/strtab.c258
-rw-r--r--usr/src/tools/ctf/cvt/strtab.h69
-rw-r--r--usr/src/tools/ctf/cvt/tdata.c479
-rw-r--r--usr/src/tools/ctf/cvt/traverse.c226
-rw-r--r--usr/src/tools/ctf/cvt/traverse.h71
-rw-r--r--usr/src/tools/ctf/cvt/util.c236
40 files changed, 4 insertions, 12373 deletions
diff --git a/usr/src/Makefile.master b/usr/src/Makefile.master
index 5dee3d84a8..375f4fb01f 100644
--- a/usr/src/Makefile.master
+++ b/usr/src/Makefile.master
@@ -993,15 +993,6 @@ CTFCVTFLAGS= -L VERSION
#
CTFMRGFLAGS=
-#
-# Make the transition between old and new CTF Tools. The new ctf tools
-# do not support stabs (eg. Sun Studio). By setting BUILD_OLD_CTF_TOOLS
-# here or in the environment file, the old ones will be built.
-#
-BUILD_NEW_CTF_TOOLS=
-BUILD_OLD_CTF_TOOLS=$(POUND_SIGN)
-$(BUILD_OLD_CTF_TOOLS)BUILD_NEW_CTF_TOOLS= $(POUND_SIGN)
-
CTFCONVERT_O = $(CTFCONVERT) $(CTFCVTFLAGS) $@
# Rules (normally from make.rules) and macros which are used for post
diff --git a/usr/src/cmd/ctfconvert/ctfconvert.c b/usr/src/cmd/ctfconvert/ctfconvert.c
index 9c93da38f4..2633207693 100644
--- a/usr/src/cmd/ctfconvert/ctfconvert.c
+++ b/usr/src/cmd/ctfconvert/ctfconvert.c
@@ -10,7 +10,7 @@
*/
/*
- * Copyright (c) 2019, Joyent, Inc.
+ * Copyright 2019 Joyent, Inc.
*/
/*
@@ -39,8 +39,6 @@
#define CTFCONVERT_DEFAULT_NTHREADS 4
-#define CTFCONVERT_ALTEXEC "CTFCONVERT_ALTEXEC"
-
static char *ctfconvert_progname;
static void
@@ -222,28 +220,6 @@ ctfconvert_fixup_genunix(ctf_file_t *fp)
VERIFY(ctf_type_size(fp, cpuid) == sz);
}
-static void
-ctfconvert_altexec(char **argv)
-{
- const char *alt;
- char *altexec;
-
- alt = getenv(CTFCONVERT_ALTEXEC);
- if (alt == NULL || *alt == '\0')
- return;
-
- altexec = strdup(alt);
- if (altexec == NULL)
- ctfconvert_fatal("failed to allocate memory for altexec\n");
- if (unsetenv(CTFCONVERT_ALTEXEC) != 0)
- ctfconvert_fatal("failed to unset %s from environment: %s\n",
- CTFCONVERT_ALTEXEC, strerror(errno));
-
- (void) execv(altexec, argv);
- ctfconvert_fatal("failed to execute alternate program %s: %s",
- altexec, strerror(errno));
-}
-
int
main(int argc, char *argv[])
{
@@ -264,8 +240,6 @@ main(int argc, char *argv[])
ctfconvert_progname = basename(argv[0]);
- ctfconvert_altexec(argv);
-
while ((c = getopt(argc, argv, ":ij:kl:L:mo:X")) != -1) {
switch (c) {
case 'i':
diff --git a/usr/src/cmd/ctfmerge/ctfmerge.c b/usr/src/cmd/ctfmerge/ctfmerge.c
index 23328fefc2..245cb180b4 100644
--- a/usr/src/cmd/ctfmerge/ctfmerge.c
+++ b/usr/src/cmd/ctfmerge/ctfmerge.c
@@ -45,7 +45,6 @@ static uint_t g_nctf;
#define CTFMERGE_USAGE 2
#define CTFMERGE_DEFAULT_NTHREADS 8
-#define CTFMERGE_ALTEXEC "CTFMERGE_ALTEXEC"
static void __attribute__((__noreturn__))
ctfmerge_fatal(const char *fmt, ...)
@@ -312,28 +311,6 @@ ctfmerge_usage(const char *fmt, ...)
g_progname);
}
-static void
-ctfmerge_altexec(char **argv)
-{
- const char *alt;
- char *altexec;
-
- alt = getenv(CTFMERGE_ALTEXEC);
- if (alt == NULL || *alt == '\0')
- return;
-
- altexec = strdup(alt);
- if (altexec == NULL)
- ctfmerge_fatal("failed to allocate memory for altexec\n");
- if (unsetenv(CTFMERGE_ALTEXEC) != 0)
- ctfmerge_fatal("failed to unset %s from environment: %s\n",
- CTFMERGE_ALTEXEC, strerror(errno));
-
- (void) execv(altexec, argv);
- ctfmerge_fatal("failed to execute alternate program %s: %s",
- altexec, strerror(errno));
-}
-
int
main(int argc, char *argv[])
{
@@ -349,8 +326,6 @@ main(int argc, char *argv[])
g_progname = basename(argv[0]);
- ctfmerge_altexec(argv);
-
/*
* We support a subset of the old CTF merge flags, mostly for
* compatibility.
diff --git a/usr/src/tools/ctf/Makefile b/usr/src/tools/ctf/Makefile
index 3ea3da7ca1..172509dc2f 100644
--- a/usr/src/tools/ctf/Makefile
+++ b/usr/src/tools/ctf/Makefile
@@ -23,12 +23,12 @@
# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
+# Copyright 2019 Joyent, Inc.
+#
include ../Makefile.tools
-SUBDIRS = stabs ctfstrip libctf ctfdiff ctfdump
-$(BUILD_OLD_CTF_TOOLS)SUBDIRS += cvt
-$(BUILD_NEW_CTF_TOOLS)SUBDIRS += ctfmerge ctfconvert
+SUBDIRS = stabs ctfstrip libctf ctfdiff ctfdump ctfmerge ctfconvert
.PARALLEL: $(SUBDIRS)
diff --git a/usr/src/tools/ctf/cvt/Makefile b/usr/src/tools/ctf/cvt/Makefile
deleted file mode 100644
index 16d8280cdd..0000000000
--- a/usr/src/tools/ctf/cvt/Makefile
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# 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.
-#
-#ident "%Z%%M% %I% %E% SMI"
-
-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/cvt/Makefile.com b/usr/src/tools/ctf/cvt/Makefile.com
deleted file mode 100644
index 1771505c9e..0000000000
--- a/usr/src/tools/ctf/cvt/Makefile.com
+++ /dev/null
@@ -1,91 +0,0 @@
-#
-# 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.ctf
-
-.KEEP_STATE:
-.PARALLEL:
-
-PROG=ctfconvert ctfmerge
-
-GENSRCS= \
- alist.c \
- altexec.c \
- barrier.c \
- ctf.c \
- fifo.c \
- hash.c \
- iidesc.c \
- input.c \
- list.c \
- memory.c \
- merge.c \
- output.c \
- stack.c \
- strtab.c \
- symbol.c \
- tdata.c \
- traverse.c \
- util.c
-
-CVTSRCS=$(GENSRCS) \
- ctfconvert.c \
- dwarf.c \
- stabs.c \
- fixup_tdescs.c \
- st_parse.c
-CVTOBJS=$(CVTSRCS:%.c=%.o)
-CVTLINTFILES = $(CVTSRCS:%.c=%.ln)
-
-MRGSRCS=$(GENSRCS) \
- ctfmerge.c
-MRGOBJS=$(MRGSRCS:%.c=%.o)
-MRGLINTFILES = $(MRGSRCS:%.c=%.ln)
-
-SRCS=$(CVTSRCS) $(MRGSRCS) $(CMPSRCS)
-OBJS=$(SRCS:%.c=%.o)
-LINTFILES=$(SRCS:%.c=%.ln)
-
-DWARFLDFLAGS = \
- -L$(ROOTONBLDLIBMACH) \
- '-R$$ORIGIN/../../lib/$(MACH)' \
- -ldwarf
-DWARFCPPFLAGS = -I$(SRC)/lib/libdwarf/common
-
-LDFLAGS += -L$(NATIVE_ADJUNCT)/lib
-LDLIBS += -lz -lelf
-CPPFLAGS += -D_REENTRANT
-CFLAGS += $(CTF_FLAGS)
-LINTFLAGS += -mnux
-
-CERRWARN += -_gcc=-Wno-unused
-CERRWARN += $(CNOWARN_UNINIT)
-CERRWARN += -_gcc=-Wno-switch
-
-CSTD = $(CSTD_GNU99)
-
-ctfconvert := LDFLAGS += $(DWARFLDFLAGS)
-
-dwarf.o dwarf.ln := CPPFLAGS += $(DWARFCPPFLAGS)
diff --git a/usr/src/tools/ctf/cvt/Makefile.targ b/usr/src/tools/ctf/cvt/Makefile.targ
deleted file mode 100644
index fba7b168e9..0000000000
--- a/usr/src/tools/ctf/cvt/Makefile.targ
+++ /dev/null
@@ -1,75 +0,0 @@
-#
-# 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 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-all: $(PROG)
-
-ctfconvert: $(CVTOBJS)
- $(LINK.c) -o $@ $(CVTOBJS) $(LDLIBS)
- $(POST_PROCESS)
-
-ctfmerge: $(MRGOBJS)
- $(LINK.c) -o $@ $(MRGOBJS) $(LDLIBS)
- $(POST_PROCESS)
-
-%.o: ../%.c
- $(COMPILE.c) $<
-
-%.ln: ../%.c
- $(LINT.c) -c $<
-
-$(ROOTONBLDMACHPROG): $(SELFTEST)
-$(SELFTEST): $(PROG)
-
-install: $(PROG) $(SELFTEST) .WAIT $(ROOTONBLDMACHPROG)
-
-lint: $(LINTFILES)
- $(LINT) $(LINTFLAGS) $(CVTLINTFILES)
- $(LINT) $(LINTFLAGS) $(MRGLINTFILES)
-
-clean:
- $(RM) $(OBJS)
-
-CLOBBERFILES=$(LINTFILES)
-
-#
-# After we've built ctfconvert and ctfmerge, let's use them on ourselves. The
-# RPATH in the built ctfconvert will only know how to find libdwarf if we invoke
-# the one in $(ROOT). We haven't installed it there yet, though, so we have to
-# invoke the one in $(SRC). We'll manually tell it where libdwarf is.
-#
-selftest: ctf_o ctfconvert_merge ctfmerge_merge
-
-ctf_o: $(OBJS:%.o=%_ctf)
-
-%_ctf: %.o ctfconvert
- LD_LIBRARY_PATH=$(DWARFSRCLIBDIR)/$(MACH) ./ctfconvert -l $@ $<
-
-ctfconvert_merge: ctf_o ctfmerge
- ./ctfmerge -l $@ -o ctfconvert $(CVTOBJS)
-
-ctfmerge_merge: ctf_o ctfmerge
- ./ctfmerge -l $@ -o ctfmerge $(MRGOBJS)
-
-include ../../Makefile.ctf.targ
diff --git a/usr/src/tools/ctf/cvt/alist.c b/usr/src/tools/ctf/cvt/alist.c
deleted file mode 100644
index 415a6cd333..0000000000
--- a/usr/src/tools/ctf/cvt/alist.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * 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 2001-2003 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Create, manage, and destroy association lists. alists are arrays with
- * arbitrary index types, and are also commonly known as associative arrays.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "alist.h"
-#include "memory.h"
-#include "hash.h"
-
-#define ALIST_HASH_SIZE 997
-
-struct alist {
- hash_t *al_elements;
- void (*al_namefree)(void *);
- void (*al_valfree)(void *);
-};
-
-typedef struct alist_el {
- void *ale_name;
- void *ale_value;
-} alist_el_t;
-
-static int
-alist_hash(int nbuckets, alist_el_t *el)
-{
- uintptr_t num = (uintptr_t)el->ale_name;
-
- return (num % nbuckets);
-}
-
-static int
-alist_cmp(alist_el_t *el1, alist_el_t *el2)
-{
- return ((uintptr_t)el1->ale_name != (uintptr_t)el2->ale_name);
-}
-
-alist_t *
-alist_xnew(int nbuckets, void (*namefree)(void *),
- void (*valfree)(void *), int (*hashfn)(int, void *),
- int (*cmpfn)(void *, void *))
-{
- alist_t *alist;
-
- alist = xcalloc(sizeof (alist_t));
- alist->al_elements = hash_new(nbuckets, hashfn, cmpfn);
- alist->al_namefree = namefree;
- alist->al_valfree = valfree;
-
- return (alist);
-}
-
-alist_t *
-alist_new(void (*namefree)(void *), void (*valfree)(void *))
-{
- return (alist_xnew(ALIST_HASH_SIZE, namefree, valfree,
- (int (*)())alist_hash, (int (*)())alist_cmp));
-}
-
-static void
-alist_free_cb(alist_el_t *el, alist_t *alist)
-{
- if (alist->al_namefree)
- alist->al_namefree(el->ale_name);
- if (alist->al_valfree)
- alist->al_valfree(el->ale_name);
- free(el);
-}
-
-void
-alist_free(alist_t *alist)
-{
- hash_free(alist->al_elements, (void (*)())alist_free_cb, alist);
- free(alist);
-}
-
-void
-alist_add(alist_t *alist, void *name, void *value)
-{
- alist_el_t *el;
-
- el = xmalloc(sizeof (alist_el_t));
- el->ale_name = name;
- el->ale_value = value;
- hash_add(alist->al_elements, el);
-}
-
-int
-alist_find(alist_t *alist, void *name, void **value)
-{
- alist_el_t template, *ret;
-
- template.ale_name = name;
- if (!hash_find(alist->al_elements, &template, (void **)&ret))
- return (0);
-
- if (value)
- *value = ret->ale_value;
-
- return (1);
-}
-
-typedef struct alist_iter_data {
- int (*aid_func)(void *, void *, void *);
- void *aid_priv;
-} alist_iter_data_t;
-
-static int
-alist_iter_cb(alist_el_t *el, alist_iter_data_t *aid)
-{
- return (aid->aid_func(el->ale_name, el->ale_value, aid->aid_priv));
-}
-
-int
-alist_iter(alist_t *alist, int (*func)(void *, void *, void *), void *private)
-{
- alist_iter_data_t aid;
-
- aid.aid_func = func;
- aid.aid_priv = private;
-
- return (hash_iter(alist->al_elements, (int (*)())alist_iter_cb, &aid));
-}
-
-/*
- * Debugging support. Used to print the contents of an alist.
- */
-
-void
-alist_stats(alist_t *alist, int verbose)
-{
- printf("Alist statistics\n");
- hash_stats(alist->al_elements, verbose);
-}
-
-static int alist_def_print_cb_key_int = 1;
-static int alist_def_print_cb_value_int = 1;
-
-static int
-alist_def_print_cb(void *key, void *value)
-{
- printf("Key: ");
- if (alist_def_print_cb_key_int == 1)
- printf("%5d ", (int)key);
- else
- printf("%s\n", (char *)key);
-
- printf("Value: ");
- if (alist_def_print_cb_value_int == 1)
- printf("%5d\n", (int)value);
- else
- printf("%s\n", (char *)key);
-
- return (1);
-}
-
-static int
-alist_dump_cb(void *node, void *private)
-{
- int (*printer)(void *, void *) = (int (*)())private;
- alist_el_t *el = node;
-
- printer(el->ale_name, el->ale_value);
-
- return (1);
-}
-
-int
-alist_dump(alist_t *alist, int (*printer)(void *, void *))
-{
- if (!printer)
- printer = alist_def_print_cb;
-
- return (hash_iter(alist->al_elements, alist_dump_cb, (void *)printer));
-}
diff --git a/usr/src/tools/ctf/cvt/alist.h b/usr/src/tools/ctf/cvt/alist.h
deleted file mode 100644
index ec49df1a35..0000000000
--- a/usr/src/tools/ctf/cvt/alist.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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 2001-2003 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _ASSOC_H
-#define _ASSOC_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Create, manage, and destroy association lists. alists are arrays with
- * arbitrary index types.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct alist alist_t;
-
-alist_t *alist_new(void (*)(void *), void (*)(void *));
-alist_t *alist_xnew(int, void (*)(void *), void (*)(void *),
- int (*)(int, void *), int (*)(void *, void *));
-void alist_free(alist_t *);
-void alist_add(alist_t *, void *, void *);
-int alist_find(alist_t *, void *, void **);
-int alist_iter(alist_t *, int (*)(void *, void *, void *), void *);
-void alist_stats(alist_t *, int);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _ASSOC_H */
diff --git a/usr/src/tools/ctf/cvt/altexec.c b/usr/src/tools/ctf/cvt/altexec.c
deleted file mode 100644
index c986c0731a..0000000000
--- a/usr/src/tools/ctf/cvt/altexec.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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) 2015, Joyent, Inc.
- */
-
-/*
- * Alternate execution engine for CTF tools
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "ctftools.h"
-
-void
-ctf_altexec(const char *env, int argc, char **argv)
-{
- const char *alt;
- char *altexec;
-
- alt = getenv(env);
- if (alt == NULL || *alt == '\0')
- return;
-
- altexec = strdup(alt);
- if (altexec == NULL)
- terminate("failed to allocate memory for altexec\n");
-
- if (unsetenv(env) != 0)
- aborterr("failed to remove %s from environment", env);
-
- (void) execv(altexec, argv);
- terminate("failed to altexec %s", altexec);
-}
diff --git a/usr/src/tools/ctf/cvt/barrier.c b/usr/src/tools/ctf/cvt/barrier.c
deleted file mode 100644
index d91fbf44db..0000000000
--- a/usr/src/tools/ctf/cvt/barrier.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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 2002 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * This file implements a barrier, a synchronization primitive designed to allow
- * threads to wait for each other at given points. Barriers are initialized
- * with a given number of threads, n, using barrier_init(). When a thread calls
- * barrier_wait(), that thread blocks until n - 1 other threads reach the
- * barrier_wait() call using the same barrier_t. When n threads have reached
- * the barrier, they are all awakened and sent on their way. One of the threads
- * returns from barrier_wait() with a return code of 1; the remaining threads
- * get a return code of 0.
- */
-
-#include <pthread.h>
-#include <synch.h>
-#include <stdio.h>
-
-#include "barrier.h"
-
-void
-barrier_init(barrier_t *bar, int nthreads)
-{
- pthread_mutex_init(&bar->bar_lock, NULL);
- sema_init(&bar->bar_sem, 0, USYNC_THREAD, NULL);
-
- bar->bar_numin = 0;
- bar->bar_nthr = nthreads;
-}
-
-int
-barrier_wait(barrier_t *bar)
-{
- pthread_mutex_lock(&bar->bar_lock);
-
- if (++bar->bar_numin < bar->bar_nthr) {
- pthread_mutex_unlock(&bar->bar_lock);
- sema_wait(&bar->bar_sem);
-
- return (0);
-
- } else {
- int i;
-
- /* reset for next use */
- bar->bar_numin = 0;
- for (i = 1; i < bar->bar_nthr; i++)
- sema_post(&bar->bar_sem);
- pthread_mutex_unlock(&bar->bar_lock);
-
- return (1);
- }
-}
diff --git a/usr/src/tools/ctf/cvt/barrier.h b/usr/src/tools/ctf/cvt/barrier.h
deleted file mode 100644
index 3a62f3082e..0000000000
--- a/usr/src/tools/ctf/cvt/barrier.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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 2002 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _BARRIER_H
-#define _BARRIER_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * APIs for the barrier synchronization primitive.
- */
-
-#include <synch.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct barrier {
- pthread_mutex_t bar_lock; /* protects bar_numin */
- int bar_numin; /* current number of waiters */
-
- sema_t bar_sem; /* where everyone waits */
- int bar_nthr; /* # of waiters to trigger release */
-} barrier_t;
-
-extern void barrier_init(barrier_t *, int);
-extern int barrier_wait(barrier_t *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _BARRIER_H */
diff --git a/usr/src/tools/ctf/cvt/compare.c b/usr/src/tools/ctf/cvt/compare.c
deleted file mode 100644
index 26037f8a53..0000000000
--- a/usr/src/tools/ctf/cvt/compare.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * This is a test program designed to catch mismerges and mistranslations from
- * stabs to CTF.
- *
- * Given a file with stabs data and a file with CTF data, determine whether
- * or not all of the data structures and objects described by the stabs data
- * are present in the CTF data.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#include "ctftools.h"
-
-char *progname;
-int debug_level = DEBUG_LEVEL;
-
-static void
-usage(void)
-{
- fprintf(stderr, "Usage: %s ctf_file stab_file\n", progname);
-}
-
-int
-main(int argc, char **argv)
-{
- tdata_t *ctftd, *stabrtd, *stabtd, *difftd;
- char *ctfname, *stabname;
- int new;
-
- progname = argv[0];
-
- if (argc != 3) {
- usage();
- exit(2);
- }
-
- ctfname = argv[1];
- stabname = argv[2];
-
- stabrtd = tdata_new();
- stabtd = tdata_new();
- difftd = tdata_new();
-
- if (read_stabs(stabrtd, stabname, 0) != 0)
- merge_into_master(stabrtd, stabtd, NULL, 1);
- else if (read_ctf(&stabname, 1, NULL, read_ctf_save_cb, &stabtd, 0)
- == 0)
- terminate("%s doesn't have stabs or CTF\n", stabname);
-
- if (read_ctf(&ctfname, 1, NULL, read_ctf_save_cb, &ctftd, 0) == 0)
- terminate("%s doesn't contain CTF data\n", ctfname);
-
- merge_into_master(stabtd, ctftd, difftd, 0);
-
- if ((new = hash_count(difftd->td_iihash)) != 0) {
- (void) hash_iter(difftd->td_iihash, (int (*)())iidesc_dump,
- NULL);
- terminate("%s grew by %d\n", stabname, new);
- }
-
- return (0);
-}
diff --git a/usr/src/tools/ctf/cvt/ctf.c b/usr/src/tools/ctf/cvt/ctf.c
deleted file mode 100644
index 83f09cb43e..0000000000
--- a/usr/src/tools/ctf/cvt/ctf.c
+++ /dev/null
@@ -1,1282 +0,0 @@
-/*
- * 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 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * Create and parse buffers containing CTF data.
- */
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <ctype.h>
-#include <zlib.h>
-#include <elf.h>
-
-#include "ctf_headers.h"
-#include "ctftools.h"
-#include "strtab.h"
-#include "memory.h"
-
-/*
- * Name of the file currently being read, used to print error messages. We
- * assume that only one file will be read at a time, and thus make no attempt
- * to allow curfile to be used simultaneously by multiple threads.
- *
- * The value is only valid during a call to ctf_load.
- */
-char *curfile;
-
-#define CTF_BUF_CHUNK_SIZE (64 * 1024)
-#define RES_BUF_CHUNK_SIZE (64 * 1024)
-
-struct ctf_buf {
- strtab_t ctb_strtab; /* string table */
- caddr_t ctb_base; /* pointer to base of buffer */
- caddr_t ctb_end; /* pointer to end of buffer */
- caddr_t ctb_ptr; /* pointer to empty buffer space */
- size_t ctb_size; /* size of buffer */
- int nptent; /* number of processed types */
- int ntholes; /* number of type holes */
-};
-
-/*PRINTFLIKE1*/
-static void
-parseterminate(char *fmt, ...)
-{
- static char msgbuf[1024]; /* sigh */
- va_list ap;
-
- va_start(ap, fmt);
- vsnprintf(msgbuf, sizeof (msgbuf), fmt, ap);
- va_end(ap);
-
- terminate("%s: %s\n", curfile, msgbuf);
-}
-
-void
-ctf_buf_grow(ctf_buf_t *b)
-{
- off_t ptroff = b->ctb_ptr - b->ctb_base;
-
- b->ctb_size += CTF_BUF_CHUNK_SIZE;
- b->ctb_base = xrealloc(b->ctb_base, b->ctb_size);
- b->ctb_end = b->ctb_base + b->ctb_size;
- b->ctb_ptr = b->ctb_base + ptroff;
-}
-
-ctf_buf_t *
-ctf_buf_new(void)
-{
- ctf_buf_t *b = xcalloc(sizeof (ctf_buf_t));
-
- strtab_create(&b->ctb_strtab);
- ctf_buf_grow(b);
-
- return (b);
-}
-
-void
-ctf_buf_free(ctf_buf_t *b)
-{
- strtab_destroy(&b->ctb_strtab);
- free(b->ctb_base);
- free(b);
-}
-
-uint_t
-ctf_buf_cur(ctf_buf_t *b)
-{
- return (b->ctb_ptr - b->ctb_base);
-}
-
-void
-ctf_buf_write(ctf_buf_t *b, const void *p, size_t n)
-{
- size_t len;
-
- while (n != 0) {
- if (b->ctb_ptr == b->ctb_end)
- ctf_buf_grow(b);
-
- len = MIN((size_t)(b->ctb_end - b->ctb_ptr), n);
- bcopy(p, b->ctb_ptr, len);
- b->ctb_ptr += len;
-
- p = (char *)p + len;
- n -= len;
- }
-}
-
-static int
-write_label(labelent_t *le, ctf_buf_t *b)
-{
- ctf_lblent_t ctl;
-
- ctl.ctl_label = strtab_insert(&b->ctb_strtab, le->le_name);
- ctl.ctl_typeidx = le->le_idx;
-
- ctf_buf_write(b, &ctl, sizeof (ctl));
-
- return (1);
-}
-
-static void
-write_objects(iidesc_t *idp, ctf_buf_t *b)
-{
- ushort_t id = (idp ? idp->ii_dtype->t_id : 0);
-
- ctf_buf_write(b, &id, sizeof (id));
-
- debug(3, "Wrote object %s (%d)\n", (idp ? idp->ii_name : "(null)"), id);
-}
-
-static void
-write_functions(iidesc_t *idp, ctf_buf_t *b)
-{
- ushort_t fdata[2];
- ushort_t id;
- int nargs;
- int i;
-
- if (!idp) {
- fdata[0] = 0;
- ctf_buf_write(b, &fdata[0], sizeof (fdata[0]));
-
- debug(3, "Wrote function (null)\n");
- return;
- }
-
- nargs = idp->ii_nargs + (idp->ii_vargs != 0);
-
- if (nargs > CTF_MAX_VLEN) {
- terminate("function %s has too many args: %d > %d\n",
- idp->ii_name, nargs, CTF_MAX_VLEN);
- }
-
- fdata[0] = CTF_TYPE_INFO(CTF_K_FUNCTION, 1, nargs);
- fdata[1] = idp->ii_dtype->t_id;
- ctf_buf_write(b, fdata, sizeof (fdata));
-
- for (i = 0; i < idp->ii_nargs; i++) {
- id = idp->ii_args[i]->t_id;
- ctf_buf_write(b, &id, sizeof (id));
- }
-
- if (idp->ii_vargs) {
- id = 0;
- ctf_buf_write(b, &id, sizeof (id));
- }
-
- debug(3, "Wrote function %s (%d args)\n", idp->ii_name, nargs);
-}
-
-/*
- * Depending on the size of the type being described, either a ctf_stype_t (for
- * types with size < CTF_LSTRUCT_THRESH) or a ctf_type_t (all others) will be
- * written. We isolate the determination here so the rest of the writer code
- * doesn't need to care.
- */
-static void
-write_sized_type_rec(ctf_buf_t *b, ctf_type_t *ctt, size_t size)
-{
- if (size > CTF_MAX_SIZE) {
- ctt->ctt_size = CTF_LSIZE_SENT;
- ctt->ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size);
- ctt->ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size);
- ctf_buf_write(b, ctt, sizeof (*ctt));
- } else {
- ctf_stype_t *cts = (ctf_stype_t *)ctt;
-
- cts->ctt_size = (ushort_t)size;
- ctf_buf_write(b, cts, sizeof (*cts));
- }
-}
-
-static void
-write_unsized_type_rec(ctf_buf_t *b, ctf_type_t *ctt)
-{
- ctf_stype_t *cts = (ctf_stype_t *)ctt;
-
- ctf_buf_write(b, cts, sizeof (*cts));
-}
-
-static int
-write_type(tdesc_t *tp, ctf_buf_t *b)
-{
- elist_t *ep;
- mlist_t *mp;
- intr_t *ip;
-
- size_t offset;
- uint_t encoding;
- uint_t data;
- int isroot = tp->t_flags & TDESC_F_ISROOT;
- int i;
-
- ctf_type_t ctt;
- ctf_array_t cta;
- ctf_member_t ctm;
- ctf_lmember_t ctlm;
- ctf_enum_t cte;
- ushort_t id;
-
- ctlm.ctlm_pad = 0;
-
- /*
- * There shouldn't be any holes in the type list (where a hole is
- * defined as two consecutive tdescs without consecutive ids), but
- * check for them just in case. If we do find holes, we need to make
- * fake entries to fill the holes, or we won't be able to reconstruct
- * the tree from the written data.
- */
- if (++b->nptent < CTF_TYPE_TO_INDEX(tp->t_id)) {
- debug(2, "genctf: type hole from %d < x < %d\n",
- b->nptent - 1, CTF_TYPE_TO_INDEX(tp->t_id));
-
- ctt.ctt_name = CTF_TYPE_NAME(CTF_STRTAB_0, 0);
- ctt.ctt_info = CTF_TYPE_INFO(0, 0, 0);
- while (b->nptent < CTF_TYPE_TO_INDEX(tp->t_id)) {
- write_sized_type_rec(b, &ctt, 0);
- b->nptent++;
- }
- }
-
- offset = strtab_insert(&b->ctb_strtab, tp->t_name);
- ctt.ctt_name = CTF_TYPE_NAME(CTF_STRTAB_0, offset);
-
- switch (tp->t_type) {
- case INTRINSIC:
- ip = tp->t_intr;
- if (ip->intr_type == INTR_INT)
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_INTEGER,
- isroot, 1);
- else
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_FLOAT, isroot, 1);
- write_sized_type_rec(b, &ctt, tp->t_size);
-
- encoding = 0;
-
- if (ip->intr_type == INTR_INT) {
- if (ip->intr_signed)
- encoding |= CTF_INT_SIGNED;
- if (ip->intr_iformat == 'c')
- encoding |= CTF_INT_CHAR;
- else if (ip->intr_iformat == 'b')
- encoding |= CTF_INT_BOOL;
- else if (ip->intr_iformat == 'v')
- encoding |= CTF_INT_VARARGS;
- } else
- encoding = ip->intr_fformat;
-
- data = CTF_INT_DATA(encoding, ip->intr_offset, ip->intr_nbits);
- ctf_buf_write(b, &data, sizeof (data));
- break;
-
- case POINTER:
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_POINTER, isroot, 0);
- ctt.ctt_type = tp->t_tdesc->t_id;
- write_unsized_type_rec(b, &ctt);
- break;
-
- case ARRAY:
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_ARRAY, isroot, 1);
- write_sized_type_rec(b, &ctt, tp->t_size);
-
- cta.cta_contents = tp->t_ardef->ad_contents->t_id;
- cta.cta_index = tp->t_ardef->ad_idxtype->t_id;
- cta.cta_nelems = tp->t_ardef->ad_nelems;
- ctf_buf_write(b, &cta, sizeof (cta));
- break;
-
- case STRUCT:
- case UNION:
- for (i = 0, mp = tp->t_members; mp != NULL; mp = mp->ml_next)
- i++; /* count up struct or union members */
-
- if (i > CTF_MAX_VLEN) {
- terminate("sou %s has too many members: %d > %d\n",
- tdesc_name(tp), i, CTF_MAX_VLEN);
- }
-
- if (tp->t_type == STRUCT)
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_STRUCT, isroot, i);
- else
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_UNION, isroot, i);
-
- write_sized_type_rec(b, &ctt, tp->t_size);
-
- if (tp->t_size < CTF_LSTRUCT_THRESH) {
- for (mp = tp->t_members; mp != NULL; mp = mp->ml_next) {
- offset = strtab_insert(&b->ctb_strtab,
- mp->ml_name);
-
- ctm.ctm_name = CTF_TYPE_NAME(CTF_STRTAB_0,
- offset);
- ctm.ctm_type = mp->ml_type->t_id;
- ctm.ctm_offset = mp->ml_offset;
- ctf_buf_write(b, &ctm, sizeof (ctm));
- }
- } else {
- for (mp = tp->t_members; mp != NULL; mp = mp->ml_next) {
- offset = strtab_insert(&b->ctb_strtab,
- mp->ml_name);
-
- ctlm.ctlm_name = CTF_TYPE_NAME(CTF_STRTAB_0,
- offset);
- ctlm.ctlm_type = mp->ml_type->t_id;
- ctlm.ctlm_offsethi =
- CTF_OFFSET_TO_LMEMHI(mp->ml_offset);
- ctlm.ctlm_offsetlo =
- CTF_OFFSET_TO_LMEMLO(mp->ml_offset);
- ctf_buf_write(b, &ctlm, sizeof (ctlm));
- }
- }
- break;
-
- case ENUM:
- for (i = 0, ep = tp->t_emem; ep != NULL; ep = ep->el_next)
- i++; /* count up enum members */
-
- if (i > CTF_MAX_VLEN) {
- terminate("enum %s has too many values: %d > %d\n",
- tdesc_name(tp), i, CTF_MAX_VLEN);
- }
-
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_ENUM, isroot, i);
- write_sized_type_rec(b, &ctt, tp->t_size);
-
- for (ep = tp->t_emem; ep != NULL; ep = ep->el_next) {
- offset = strtab_insert(&b->ctb_strtab, ep->el_name);
- cte.cte_name = CTF_TYPE_NAME(CTF_STRTAB_0, offset);
- cte.cte_value = ep->el_number;
- ctf_buf_write(b, &cte, sizeof (cte));
- }
- break;
-
- case FORWARD:
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_FORWARD, isroot, 0);
- ctt.ctt_type = 0;
- write_unsized_type_rec(b, &ctt);
- break;
-
- case TYPEDEF:
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_TYPEDEF, isroot, 0);
- ctt.ctt_type = tp->t_tdesc->t_id;
- write_unsized_type_rec(b, &ctt);
- break;
-
- case VOLATILE:
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_VOLATILE, isroot, 0);
- ctt.ctt_type = tp->t_tdesc->t_id;
- write_unsized_type_rec(b, &ctt);
- break;
-
- case CONST:
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_CONST, isroot, 0);
- ctt.ctt_type = tp->t_tdesc->t_id;
- write_unsized_type_rec(b, &ctt);
- break;
-
- case FUNCTION:
- i = tp->t_fndef->fn_nargs + tp->t_fndef->fn_vargs;
-
- if (i > CTF_MAX_VLEN) {
- terminate("function %s has too many args: %d > %d\n",
- i, CTF_MAX_VLEN);
- }
-
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_FUNCTION, isroot, i);
- ctt.ctt_type = tp->t_fndef->fn_ret->t_id;
- write_unsized_type_rec(b, &ctt);
-
- for (i = 0; i < tp->t_fndef->fn_nargs; i++) {
- id = tp->t_fndef->fn_args[i]->t_id;
- ctf_buf_write(b, &id, sizeof (id));
- }
-
- if (tp->t_fndef->fn_vargs) {
- id = 0;
- ctf_buf_write(b, &id, sizeof (id));
- i++;
- }
-
- if (i & 1) {
- id = 0;
- ctf_buf_write(b, &id, sizeof (id));
- }
- break;
-
- case RESTRICT:
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_RESTRICT, isroot, 0);
- ctt.ctt_type = tp->t_tdesc->t_id;
- write_unsized_type_rec(b, &ctt);
- break;
-
- default:
- warning("Can't write unknown type %d\n", tp->t_type);
- }
-
- debug(3, "Wrote type %d %s\n", tp->t_id, tdesc_name(tp));
-
- return (1);
-}
-
-typedef struct resbuf {
- caddr_t rb_base;
- caddr_t rb_ptr;
- size_t rb_size;
- z_stream rb_zstr;
-} resbuf_t;
-
-static void
-rbzs_grow(resbuf_t *rb)
-{
- off_t ptroff = (caddr_t)rb->rb_zstr.next_out - rb->rb_base;
-
- rb->rb_size += RES_BUF_CHUNK_SIZE;
- rb->rb_base = xrealloc(rb->rb_base, rb->rb_size);
- rb->rb_ptr = rb->rb_base + ptroff;
- rb->rb_zstr.next_out = (Bytef *)(rb->rb_ptr);
- rb->rb_zstr.avail_out += RES_BUF_CHUNK_SIZE;
-}
-
-static void
-compress_start(resbuf_t *rb)
-{
- int rc;
-
- rb->rb_zstr.zalloc = (alloc_func)0;
- rb->rb_zstr.zfree = (free_func)0;
- rb->rb_zstr.opaque = (voidpf)0;
-
- if ((rc = deflateInit(&rb->rb_zstr, Z_BEST_COMPRESSION)) != Z_OK)
- parseterminate("zlib start failed: %s", zError(rc));
-}
-
-static ssize_t
-compress_buffer(const void *buf, size_t n, void *data)
-{
- resbuf_t *rb = (resbuf_t *)data;
- int rc;
-
- rb->rb_zstr.next_out = (Bytef *)rb->rb_ptr;
- rb->rb_zstr.avail_out = rb->rb_size - (rb->rb_ptr - rb->rb_base);
- rb->rb_zstr.next_in = (Bytef *)buf;
- rb->rb_zstr.avail_in = n;
-
- while (rb->rb_zstr.avail_in) {
- if (rb->rb_zstr.avail_out == 0)
- rbzs_grow(rb);
-
- if ((rc = deflate(&rb->rb_zstr, Z_NO_FLUSH)) != Z_OK)
- parseterminate("zlib deflate failed: %s", zError(rc));
- }
- rb->rb_ptr = (caddr_t)rb->rb_zstr.next_out;
-
- return (n);
-}
-
-static void
-compress_flush(resbuf_t *rb, int type)
-{
- int rc;
-
- for (;;) {
- if (rb->rb_zstr.avail_out == 0)
- rbzs_grow(rb);
-
- rc = deflate(&rb->rb_zstr, type);
- if ((type == Z_FULL_FLUSH && rc == Z_BUF_ERROR) ||
- (type == Z_FINISH && rc == Z_STREAM_END))
- break;
- else if (rc != Z_OK)
- parseterminate("zlib finish failed: %s", zError(rc));
- }
- rb->rb_ptr = (caddr_t)rb->rb_zstr.next_out;
-}
-
-static void
-compress_end(resbuf_t *rb)
-{
- int rc;
-
- compress_flush(rb, Z_FINISH);
-
- if ((rc = deflateEnd(&rb->rb_zstr)) != Z_OK)
- parseterminate("zlib end failed: %s", zError(rc));
-}
-
-/*
- * Pad the buffer to a power-of-2 boundary
- */
-static void
-pad_buffer(ctf_buf_t *buf, int align)
-{
- uint_t cur = ctf_buf_cur(buf);
- ssize_t topad = (align - (cur % align)) % align;
- static const char pad[8] = { 0 };
-
- while (topad > 0) {
- ctf_buf_write(buf, pad, (topad > 8 ? 8 : topad));
- topad -= 8;
- }
-}
-
-static ssize_t
-bcopy_data(const void *buf, size_t n, void *data)
-{
- caddr_t *posp = (caddr_t *)data;
- bcopy(buf, *posp, n);
- *posp += n;
- return (n);
-}
-
-static caddr_t
-write_buffer(ctf_header_t *h, ctf_buf_t *buf, size_t *resszp)
-{
- caddr_t outbuf;
- caddr_t bufpos;
-
- outbuf = xmalloc(sizeof (ctf_header_t) + (buf->ctb_ptr - buf->ctb_base)
- + buf->ctb_strtab.str_size);
-
- bufpos = outbuf;
- (void) bcopy_data(h, sizeof (ctf_header_t), &bufpos);
- (void) bcopy_data(buf->ctb_base, buf->ctb_ptr - buf->ctb_base,
- &bufpos);
- (void) strtab_write(&buf->ctb_strtab, bcopy_data, &bufpos);
- *resszp = bufpos - outbuf;
- return (outbuf);
-}
-
-/*
- * Create the compression buffer, and fill it with the CTF and string
- * table data. We flush the compression state between the two so the
- * dictionary used for the string tables won't be polluted with values
- * that made sense for the CTF data.
- */
-static caddr_t
-write_compressed_buffer(ctf_header_t *h, ctf_buf_t *buf, size_t *resszp)
-{
- resbuf_t resbuf;
- resbuf.rb_size = RES_BUF_CHUNK_SIZE;
- resbuf.rb_base = xmalloc(resbuf.rb_size);
- bcopy(h, resbuf.rb_base, sizeof (ctf_header_t));
- resbuf.rb_ptr = resbuf.rb_base + sizeof (ctf_header_t);
-
- compress_start(&resbuf);
- (void) compress_buffer(buf->ctb_base, buf->ctb_ptr - buf->ctb_base,
- &resbuf);
- compress_flush(&resbuf, Z_FULL_FLUSH);
- (void) strtab_write(&buf->ctb_strtab, compress_buffer, &resbuf);
- compress_end(&resbuf);
-
- *resszp = (resbuf.rb_ptr - resbuf.rb_base);
- return (resbuf.rb_base);
-}
-
-caddr_t
-ctf_gen(iiburst_t *iiburst, size_t *resszp, int do_compress)
-{
- ctf_buf_t *buf = ctf_buf_new();
- ctf_header_t h;
- caddr_t outbuf;
-
- int i;
-
- /*
- * Prepare the header, and create the CTF output buffers. The data
- * object section and function section are both lists of 2-byte
- * integers; we pad these out to the next 4-byte boundary if needed.
- */
- h.cth_magic = CTF_MAGIC;
- h.cth_version = CTF_VERSION;
- h.cth_flags = do_compress ? CTF_F_COMPRESS : 0;
- h.cth_parlabel = strtab_insert(&buf->ctb_strtab,
- iiburst->iib_td->td_parlabel);
- h.cth_parname = strtab_insert(&buf->ctb_strtab,
- iiburst->iib_td->td_parname);
-
- h.cth_lbloff = 0;
- (void) list_iter(iiburst->iib_td->td_labels, (int (*)())write_label,
- buf);
-
- pad_buffer(buf, 2);
- h.cth_objtoff = ctf_buf_cur(buf);
- for (i = 0; i < iiburst->iib_nobjts; i++)
- write_objects(iiburst->iib_objts[i], buf);
-
- pad_buffer(buf, 2);
- h.cth_funcoff = ctf_buf_cur(buf);
- for (i = 0; i < iiburst->iib_nfuncs; i++)
- write_functions(iiburst->iib_funcs[i], buf);
-
- pad_buffer(buf, 4);
- h.cth_typeoff = ctf_buf_cur(buf);
- (void) list_iter(iiburst->iib_types, (int (*)())write_type, buf);
-
- debug(2, "CTF wrote %d types\n", list_count(iiburst->iib_types));
-
- h.cth_stroff = ctf_buf_cur(buf);
- h.cth_strlen = strtab_size(&buf->ctb_strtab);
-
- /*
- * We only do compression for ctfmerge, as ctfconvert is only
- * supposed to be used on intermediary build objects. This is
- * significantly faster.
- */
- if (do_compress)
- outbuf = write_compressed_buffer(&h, buf, resszp);
- else
- outbuf = write_buffer(&h, buf, resszp);
-
- ctf_buf_free(buf);
- return (outbuf);
-}
-
-void
-get_ctt_size(ctf_type_t *ctt, size_t *sizep, size_t *incrementp)
-{
- if (ctt->ctt_size == CTF_LSIZE_SENT) {
- *sizep = (size_t)CTF_TYPE_LSIZE(ctt);
- *incrementp = sizeof (ctf_type_t);
- } else {
- *sizep = ctt->ctt_size;
- *incrementp = sizeof (ctf_stype_t);
- }
-}
-
-static int
-count_types(ctf_header_t *h, caddr_t data)
-{
- caddr_t dptr = data + h->cth_typeoff;
- int count = 0;
-
- dptr = data + h->cth_typeoff;
- while (dptr < data + h->cth_stroff) {
- /* LINTED - pointer alignment */
- ctf_type_t *ctt = (ctf_type_t *)dptr;
- size_t vlen = CTF_INFO_VLEN(ctt->ctt_info);
- size_t size, increment;
-
- get_ctt_size(ctt, &size, &increment);
-
- switch (CTF_INFO_KIND(ctt->ctt_info)) {
- case CTF_K_INTEGER:
- case CTF_K_FLOAT:
- dptr += 4;
- break;
- case CTF_K_POINTER:
- case CTF_K_FORWARD:
- case CTF_K_TYPEDEF:
- case CTF_K_VOLATILE:
- case CTF_K_CONST:
- case CTF_K_RESTRICT:
- case CTF_K_FUNCTION:
- dptr += sizeof (ushort_t) * (vlen + (vlen & 1));
- break;
- case CTF_K_ARRAY:
- dptr += sizeof (ctf_array_t);
- break;
- case CTF_K_STRUCT:
- case CTF_K_UNION:
- if (size < CTF_LSTRUCT_THRESH)
- dptr += sizeof (ctf_member_t) * vlen;
- else
- dptr += sizeof (ctf_lmember_t) * vlen;
- break;
- case CTF_K_ENUM:
- dptr += sizeof (ctf_enum_t) * vlen;
- break;
- case CTF_K_UNKNOWN:
- break;
- default:
- parseterminate("Unknown CTF type %d (#%d) at %#x",
- CTF_INFO_KIND(ctt->ctt_info), count, dptr - data);
- }
-
- dptr += increment;
- count++;
- }
-
- debug(3, "CTF read %d types\n", count);
-
- return (count);
-}
-
-/*
- * Resurrect the labels stored in the CTF data, returning the index associated
- * with a label provided by the caller. There are several cases, outlined
- * below. Note that, given two labels, the one associated with the lesser type
- * index is considered to be older than the other.
- *
- * 1. matchlbl == NULL - return the index of the most recent label.
- * 2. matchlbl == "BASE" - return the index of the oldest label.
- * 3. matchlbl != NULL, but doesn't match any labels in the section - warn
- * the user, and proceed as if matchlbl == "BASE" (for safety).
- * 4. matchlbl != NULL, and matches one of the labels in the section - return
- * the type index associated with the label.
- */
-static int
-resurrect_labels(ctf_header_t *h, tdata_t *td, caddr_t ctfdata, char *matchlbl)
-{
- caddr_t buf = ctfdata + h->cth_lbloff;
- caddr_t sbuf = ctfdata + h->cth_stroff;
- size_t bufsz = h->cth_objtoff - h->cth_lbloff;
- int lastidx = 0, baseidx = -1;
- char *baselabel;
- ctf_lblent_t *ctl;
-
- /* LINTED - pointer alignment */
- for (ctl = (ctf_lblent_t *)buf; (caddr_t)ctl < buf + bufsz; ctl++) {
- char *label = sbuf + ctl->ctl_label;
-
- lastidx = ctl->ctl_typeidx;
-
- debug(3, "Resurrected label %s type idx %d\n", label, lastidx);
-
- tdata_label_add(td, label, lastidx);
-
- if (baseidx == -1) {
- baseidx = lastidx;
- baselabel = label;
- if (matchlbl != NULL && streq(matchlbl, "BASE"))
- return (lastidx);
- }
-
- if (matchlbl != NULL && streq(label, matchlbl))
- return (lastidx);
- }
-
- if (matchlbl != NULL) {
- /* User provided a label that didn't match */
- warning("%s: Cannot find label `%s' - using base (%s)\n",
- curfile, matchlbl, (baselabel ? baselabel : "NONE"));
-
- tdata_label_free(td);
- tdata_label_add(td, baselabel, baseidx);
-
- return (baseidx);
- }
-
- return (lastidx);
-}
-
-static void
-resurrect_objects(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
- caddr_t ctfdata, symit_data_t *si)
-{
- caddr_t buf = ctfdata + h->cth_objtoff;
- size_t bufsz = h->cth_funcoff - h->cth_objtoff;
- caddr_t dptr;
-
- symit_reset(si);
- for (dptr = buf; dptr < buf + bufsz; dptr += 2) {
- /* LINTED - pointer alignment */
- ushort_t id = *((ushort_t *)dptr);
- iidesc_t *ii;
- GElf_Sym *sym;
-
- if (!(sym = symit_next(si, STT_OBJECT)) && id != 0) {
- parseterminate(
- "Unexpected end of object symbols at %x of %x",
- dptr - buf, bufsz);
- }
-
- if (id == 0) {
- debug(3, "Skipping null object\n");
- continue;
- } else if (id >= tdsize) {
- parseterminate("Reference to invalid type %d", id);
- }
-
- ii = iidesc_new(symit_name(si));
- ii->ii_dtype = tdarr[id];
- if (GELF_ST_BIND(sym->st_info) == STB_LOCAL) {
- ii->ii_type = II_SVAR;
- ii->ii_owner = xstrdup(symit_curfile(si));
- } else
- ii->ii_type = II_GVAR;
- hash_add(td->td_iihash, ii);
-
- debug(3, "Resurrected %s object %s (%d) from %s\n",
- (ii->ii_type == II_GVAR ? "global" : "static"),
- ii->ii_name, id, (ii->ii_owner ? ii->ii_owner : "(none)"));
- }
-}
-
-static void
-resurrect_functions(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
- caddr_t ctfdata, symit_data_t *si)
-{
- caddr_t buf = ctfdata + h->cth_funcoff;
- size_t bufsz = h->cth_typeoff - h->cth_funcoff;
- caddr_t dptr = buf;
- iidesc_t *ii;
- ushort_t info;
- ushort_t retid;
- GElf_Sym *sym;
- int i;
-
- symit_reset(si);
- while (dptr < buf + bufsz) {
- /* LINTED - pointer alignment */
- info = *((ushort_t *)dptr);
- dptr += 2;
-
- if (!(sym = symit_next(si, STT_FUNC)) && info != 0)
- parseterminate("Unexpected end of function symbols");
-
- if (info == 0) {
- debug(3, "Skipping null function (%s)\n",
- symit_name(si));
- continue;
- }
-
- /* LINTED - pointer alignment */
- retid = *((ushort_t *)dptr);
- dptr += 2;
-
- if (retid >= tdsize)
- parseterminate("Reference to invalid type %d", retid);
-
- ii = iidesc_new(symit_name(si));
- ii->ii_dtype = tdarr[retid];
- if (GELF_ST_BIND(sym->st_info) == STB_LOCAL) {
- ii->ii_type = II_SFUN;
- ii->ii_owner = xstrdup(symit_curfile(si));
- } else
- ii->ii_type = II_GFUN;
- ii->ii_nargs = CTF_INFO_VLEN(info);
- if (ii->ii_nargs)
- ii->ii_args =
- xmalloc(sizeof (tdesc_t *) * ii->ii_nargs);
-
- for (i = 0; i < ii->ii_nargs; i++, dptr += 2) {
- /* LINTED - pointer alignment */
- ushort_t id = *((ushort_t *)dptr);
- if (id >= tdsize)
- parseterminate("Reference to invalid type %d",
- id);
- ii->ii_args[i] = tdarr[id];
- }
-
- if (ii->ii_nargs && ii->ii_args[ii->ii_nargs - 1] == NULL) {
- ii->ii_nargs--;
- ii->ii_vargs = 1;
- }
-
- hash_add(td->td_iihash, ii);
-
- debug(3, "Resurrected %s function %s (%d, %d args)\n",
- (ii->ii_type == II_GFUN ? "global" : "static"),
- ii->ii_name, retid, ii->ii_nargs);
- }
-}
-
-static void
-resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
- caddr_t ctfdata, int maxid)
-{
- caddr_t buf = ctfdata + h->cth_typeoff;
- size_t bufsz = h->cth_stroff - h->cth_typeoff;
- caddr_t sbuf = ctfdata + h->cth_stroff;
- caddr_t dptr = buf;
- tdesc_t *tdp;
- uint_t data;
- uint_t encoding;
- size_t size, increment;
- int tcnt;
- int iicnt = 0;
- tid_t tid, argid;
- int kind, vlen;
- int i;
-
- elist_t **epp;
- mlist_t **mpp;
- intr_t *ip;
-
- ctf_type_t *ctt;
- ctf_array_t *cta;
- ctf_enum_t *cte;
-
- /*
- * A maxid of zero indicates a request to resurrect all types, so reset
- * maxid to the maximum type id.
- */
- if (maxid == 0)
- maxid = CTF_MAX_TYPE;
-
- for (dptr = buf, tcnt = 0, tid = 1; dptr < buf + bufsz; tcnt++, tid++) {
- if (tid > maxid)
- break;
-
- if (tid >= tdsize)
- parseterminate("Reference to invalid type %d", tid);
-
- /* LINTED - pointer alignment */
- ctt = (ctf_type_t *)dptr;
-
- get_ctt_size(ctt, &size, &increment);
- dptr += increment;
-
- tdp = tdarr[tid];
-
- if (CTF_NAME_STID(ctt->ctt_name) != CTF_STRTAB_0)
- parseterminate(
- "Unable to cope with non-zero strtab id");
- if (CTF_NAME_OFFSET(ctt->ctt_name) != 0) {
- tdp->t_name =
- xstrdup(sbuf + CTF_NAME_OFFSET(ctt->ctt_name));
- } else
- tdp->t_name = NULL;
-
- kind = CTF_INFO_KIND(ctt->ctt_info);
- vlen = CTF_INFO_VLEN(ctt->ctt_info);
-
- switch (kind) {
- case CTF_K_INTEGER:
- tdp->t_type = INTRINSIC;
- tdp->t_size = size;
-
- /* LINTED - pointer alignment */
- data = *((uint_t *)dptr);
- dptr += sizeof (uint_t);
- encoding = CTF_INT_ENCODING(data);
-
- ip = xmalloc(sizeof (intr_t));
- ip->intr_type = INTR_INT;
- ip->intr_signed = (encoding & CTF_INT_SIGNED) ? 1 : 0;
-
- if (encoding & CTF_INT_CHAR)
- ip->intr_iformat = 'c';
- else if (encoding & CTF_INT_BOOL)
- ip->intr_iformat = 'b';
- else if (encoding & CTF_INT_VARARGS)
- ip->intr_iformat = 'v';
- else
- ip->intr_iformat = '\0';
-
- ip->intr_offset = CTF_INT_OFFSET(data);
- ip->intr_nbits = CTF_INT_BITS(data);
- tdp->t_intr = ip;
- break;
-
- case CTF_K_FLOAT:
- tdp->t_type = INTRINSIC;
- tdp->t_size = size;
-
- /* LINTED - pointer alignment */
- data = *((uint_t *)dptr);
- dptr += sizeof (uint_t);
-
- ip = xcalloc(sizeof (intr_t));
- ip->intr_type = INTR_REAL;
- ip->intr_fformat = CTF_FP_ENCODING(data);
- ip->intr_offset = CTF_FP_OFFSET(data);
- ip->intr_nbits = CTF_FP_BITS(data);
- tdp->t_intr = ip;
- break;
-
- case CTF_K_POINTER:
- tdp->t_type = POINTER;
- tdp->t_tdesc = tdarr[ctt->ctt_type];
- break;
-
- case CTF_K_ARRAY:
- tdp->t_type = ARRAY;
- tdp->t_size = size;
-
- /* LINTED - pointer alignment */
- cta = (ctf_array_t *)dptr;
- dptr += sizeof (ctf_array_t);
-
- tdp->t_ardef = xmalloc(sizeof (ardef_t));
- tdp->t_ardef->ad_contents = tdarr[cta->cta_contents];
- tdp->t_ardef->ad_idxtype = tdarr[cta->cta_index];
- tdp->t_ardef->ad_nelems = cta->cta_nelems;
- break;
-
- case CTF_K_STRUCT:
- case CTF_K_UNION:
- tdp->t_type = (kind == CTF_K_STRUCT ? STRUCT : UNION);
- tdp->t_size = size;
-
- if (size < CTF_LSTRUCT_THRESH) {
- for (i = 0, mpp = &tdp->t_members; i < vlen;
- i++, mpp = &((*mpp)->ml_next)) {
- /* LINTED - pointer alignment */
- ctf_member_t *ctm = (ctf_member_t *)
- dptr;
- dptr += sizeof (ctf_member_t);
-
- *mpp = xmalloc(sizeof (mlist_t));
- (*mpp)->ml_name = xstrdup(sbuf +
- ctm->ctm_name);
- (*mpp)->ml_type = tdarr[ctm->ctm_type];
- (*mpp)->ml_offset = ctm->ctm_offset;
- (*mpp)->ml_size = 0;
- }
- } else {
- for (i = 0, mpp = &tdp->t_members; i < vlen;
- i++, mpp = &((*mpp)->ml_next)) {
- /* LINTED - pointer alignment */
- ctf_lmember_t *ctlm = (ctf_lmember_t *)
- dptr;
- dptr += sizeof (ctf_lmember_t);
-
- *mpp = xmalloc(sizeof (mlist_t));
- (*mpp)->ml_name = xstrdup(sbuf +
- ctlm->ctlm_name);
- (*mpp)->ml_type =
- tdarr[ctlm->ctlm_type];
- (*mpp)->ml_offset =
- (int)CTF_LMEM_OFFSET(ctlm);
- (*mpp)->ml_size = 0;
- }
- }
-
- *mpp = NULL;
- break;
-
- case CTF_K_ENUM:
- tdp->t_type = ENUM;
- tdp->t_size = size;
-
- for (i = 0, epp = &tdp->t_emem; i < vlen;
- i++, epp = &((*epp)->el_next)) {
- /* LINTED - pointer alignment */
- cte = (ctf_enum_t *)dptr;
- dptr += sizeof (ctf_enum_t);
-
- *epp = xmalloc(sizeof (elist_t));
- (*epp)->el_name = xstrdup(sbuf + cte->cte_name);
- (*epp)->el_number = cte->cte_value;
- }
- *epp = NULL;
- break;
-
- case CTF_K_FORWARD:
- tdp->t_type = FORWARD;
- list_add(&td->td_fwdlist, tdp);
- break;
-
- case CTF_K_TYPEDEF:
- tdp->t_type = TYPEDEF;
- tdp->t_tdesc = tdarr[ctt->ctt_type];
- break;
-
- case CTF_K_VOLATILE:
- tdp->t_type = VOLATILE;
- tdp->t_tdesc = tdarr[ctt->ctt_type];
- break;
-
- case CTF_K_CONST:
- tdp->t_type = CONST;
- tdp->t_tdesc = tdarr[ctt->ctt_type];
- break;
-
- case CTF_K_FUNCTION:
- tdp->t_type = FUNCTION;
- tdp->t_fndef = xcalloc(sizeof (fndef_t));
- tdp->t_fndef->fn_ret = tdarr[ctt->ctt_type];
-
- /* LINTED - pointer alignment */
- if (vlen > 0 && *(ushort_t *)(dptr +
- (sizeof (ushort_t) * (vlen - 1))) == 0)
- tdp->t_fndef->fn_vargs = 1;
-
- tdp->t_fndef->fn_nargs = vlen - tdp->t_fndef->fn_vargs;
- tdp->t_fndef->fn_args = xcalloc(sizeof (tdesc_t) *
- vlen - tdp->t_fndef->fn_vargs);
-
- for (i = 0; i < vlen; i++) {
- /* LINTED - pointer alignment */
- argid = *(ushort_t *)dptr;
- dptr += sizeof (ushort_t);
-
- if (argid != 0)
- tdp->t_fndef->fn_args[i] = tdarr[argid];
- }
-
- if (vlen & 1)
- dptr += sizeof (ushort_t);
- break;
-
- case CTF_K_RESTRICT:
- tdp->t_type = RESTRICT;
- tdp->t_tdesc = tdarr[ctt->ctt_type];
- break;
-
- case CTF_K_UNKNOWN:
- break;
-
- default:
- warning("Can't parse unknown CTF type %d\n", kind);
- }
-
- if (CTF_INFO_ISROOT(ctt->ctt_info)) {
- iidesc_t *ii = iidesc_new(tdp->t_name);
- if (tdp->t_type == STRUCT || tdp->t_type == UNION ||
- tdp->t_type == ENUM)
- ii->ii_type = II_SOU;
- else
- ii->ii_type = II_TYPE;
- ii->ii_dtype = tdp;
- hash_add(td->td_iihash, ii);
-
- iicnt++;
- }
-
- debug(3, "Resurrected %d %stype %s (%d)\n", tdp->t_type,
- (CTF_INFO_ISROOT(ctt->ctt_info) ? "root " : ""),
- tdesc_name(tdp), tdp->t_id);
- }
-
- debug(3, "Resurrected %d types (%d were roots)\n", tcnt, iicnt);
-}
-
-/*
- * For lack of other inspiration, we're going to take the boring route. We
- * count the number of types. This lets us malloc that many tdesc structs
- * before we start filling them in. This has the advantage of allowing us to
- * avoid a merge-esque remap step.
- */
-static tdata_t *
-ctf_parse(ctf_header_t *h, caddr_t buf, symit_data_t *si, char *label)
-{
- tdata_t *td = tdata_new();
- tdesc_t **tdarr;
- int ntypes = count_types(h, buf);
- int idx, i;
-
- /* shudder */
- tdarr = xcalloc(sizeof (tdesc_t *) * (ntypes + 1));
- tdarr[0] = NULL;
- for (i = 1; i <= ntypes; i++) {
- tdarr[i] = xcalloc(sizeof (tdesc_t));
- tdarr[i]->t_id = i;
- }
-
- td->td_parlabel = xstrdup(buf + h->cth_stroff + h->cth_parlabel);
-
- /* we have the technology - we can rebuild them */
- idx = resurrect_labels(h, td, buf, label);
-
- resurrect_objects(h, td, tdarr, ntypes + 1, buf, si);
- resurrect_functions(h, td, tdarr, ntypes + 1, buf, si);
- resurrect_types(h, td, tdarr, ntypes + 1, buf, idx);
-
- free(tdarr);
-
- td->td_nextid = ntypes + 1;
-
- return (td);
-}
-
-static size_t
-decompress_ctf(caddr_t cbuf, size_t cbufsz, caddr_t dbuf, size_t dbufsz)
-{
- z_stream zstr;
- int rc;
-
- zstr.zalloc = (alloc_func)0;
- zstr.zfree = (free_func)0;
- zstr.opaque = (voidpf)0;
-
- zstr.next_in = (Bytef *)cbuf;
- zstr.avail_in = cbufsz;
- zstr.next_out = (Bytef *)dbuf;
- zstr.avail_out = dbufsz;
-
- if ((rc = inflateInit(&zstr)) != Z_OK ||
- (rc = inflate(&zstr, Z_NO_FLUSH)) != Z_STREAM_END ||
- (rc = inflateEnd(&zstr)) != Z_OK) {
- warning("CTF decompress zlib error %s\n", zError(rc));
- return (0);
- }
-
- debug(3, "reflated %lu bytes to %lu, pointer at %d\n",
- zstr.total_in, zstr.total_out, (caddr_t)zstr.next_in - cbuf);
-
- return (zstr.total_out);
-}
-
-/*
- * Reconstruct the type tree from a given buffer of CTF data. Only the types
- * up to the type associated with the provided label, inclusive, will be
- * reconstructed. If a NULL label is provided, all types will be reconstructed.
- *
- * This function won't work on files that have been uniquified.
- */
-tdata_t *
-ctf_load(char *file, caddr_t buf, size_t bufsz, symit_data_t *si, char *label)
-{
- ctf_header_t *h;
- caddr_t ctfdata;
- size_t ctfdatasz;
- tdata_t *td;
-
- curfile = file;
-
- if (bufsz < sizeof (ctf_header_t))
- parseterminate("Corrupt CTF - short header");
-
- /* LINTED - pointer alignment */
- h = (ctf_header_t *)buf;
- buf += sizeof (ctf_header_t);
- bufsz -= sizeof (ctf_header_t);
-
- if (h->cth_magic != CTF_MAGIC)
- parseterminate("Corrupt CTF - bad magic 0x%x", h->cth_magic);
-
- if (h->cth_version != CTF_VERSION)
- parseterminate("Unknown CTF version %d", h->cth_version);
-
- ctfdatasz = h->cth_stroff + h->cth_strlen;
- if (h->cth_flags & CTF_F_COMPRESS) {
- size_t actual;
-
- ctfdata = xmalloc(ctfdatasz);
- if ((actual = decompress_ctf(buf, bufsz, ctfdata, ctfdatasz)) !=
- ctfdatasz) {
- parseterminate("Corrupt CTF - short decompression "
- "(was %d, expecting %d)", actual, ctfdatasz);
- }
- } else {
- ctfdata = buf;
- ctfdatasz = bufsz;
- }
-
- td = ctf_parse(h, ctfdata, si, label);
-
- if (h->cth_flags & CTF_F_COMPRESS)
- free(ctfdata);
-
- curfile = NULL;
-
- return (td);
-}
diff --git a/usr/src/tools/ctf/cvt/ctfconvert.c b/usr/src/tools/ctf/cvt/ctfconvert.c
deleted file mode 100644
index af005e1934..0000000000
--- a/usr/src/tools/ctf/cvt/ctfconvert.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * Given a file containing sections with stabs data, convert the stabs data to
- * CTF data, and replace the stabs sections with a CTF section.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
-#include <string.h>
-#include <fcntl.h>
-#include <libgen.h>
-#include <errno.h>
-#include <assert.h>
-
-#include "ctftools.h"
-#include "memory.h"
-
-const char *progname;
-int debug_level = DEBUG_LEVEL;
-
-static const char *infile = NULL;
-static const char *outfile = NULL;
-static int dynsym;
-
-static void
-usage(void)
-{
- (void) fprintf(stderr,
- "Usage: %s [-is] -l label | -L labelenv [-o outfile] object_file\n"
- "\n"
- " Note: if -L labelenv is specified and labelenv is not set in\n"
- " the environment, a default value is used.\n",
- progname);
-}
-
-static void
-terminate_cleanup(void)
-{
- if (!outfile) {
- fprintf(stderr, "Removing %s\n", infile);
- unlink(infile);
- }
-}
-
-static void
-handle_sig(int sig)
-{
- terminate("Caught signal %d - exiting\n", sig);
-}
-
-static int
-file_read(tdata_t *td, const char *filename, int ignore_non_c)
-{
- typedef int (*reader_f)(tdata_t *, Elf *, const char *);
- static const reader_f readers[] = {
- stabs_read,
- dw_read,
- NULL
- };
-
- source_types_t source_types;
- Elf *elf;
- int i, rc, fd;
-
- if ((fd = open(filename, O_RDONLY)) < 0)
- terminate("failed to open %s", filename);
-
- (void) elf_version(EV_CURRENT);
-
- if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
- close(fd);
- terminate("failed to read %s: %s\n", filename,
- elf_errmsg(-1));
- }
-
- source_types = built_source_types(elf, filename);
-
- if ((source_types == SOURCE_NONE || (source_types & SOURCE_UNKNOWN)) &&
- ignore_non_c) {
- debug(1, "Ignoring file %s from unknown sources\n", filename);
- exit(0);
- }
-
- for (i = 0; readers[i] != NULL; i++) {
- if ((rc = readers[i](td, elf, filename)) == 0)
- break;
-
- assert(rc < 0 && errno == ENOENT);
- }
-
- if (readers[i] == NULL) {
- /*
- * None of the readers found compatible type data.
- */
-
- if (findelfsecidx(elf, filename, ".debug") >= 0) {
- terminate("%s: DWARF version 1 is not supported\n",
- filename);
- }
-
- if (!(source_types & SOURCE_C) && ignore_non_c) {
- debug(1, "Ignoring file %s not built from C sources\n",
- filename);
- exit(0);
- }
-
- rc = 0;
- } else {
- rc = 1;
- }
-
- (void) elf_end(elf);
- (void) close(fd);
-
- return (rc);
-}
-
-int
-main(int argc, char **argv)
-{
- tdata_t *filetd, *mstrtd;
- char *label = NULL;
- char *altexec;
- int verbose = 0;
- int ignore_non_c = 0;
- int c;
-
- sighold(SIGINT);
- sighold(SIGQUIT);
- sighold(SIGTERM);
-
- progname = basename(argv[0]);
-
- ctf_altexec("CTFCONVERT_ALTEXEC", argc, argv);
-
- if (getenv("CTFCONVERT_DEBUG_LEVEL"))
- debug_level = atoi(getenv("CTFCONVERT_DEBUG_LEVEL"));
- if (getenv("CTFCONVERT_DEBUG_PARSE"))
- debug_parse = atoi(getenv("CTFCONVERT_DEBUG_PARSE"));
-
- if ((altexec = getenv("CTFCONVERT_ALTEXEC")) != NULL) {
- (void) unsetenv("CTFCONVERT_ALTEXEC");
- (void) execv(altexec, argv);
- (void) fprintf(stderr, "ctfconvert altexec failed to "
- "run %s: %s\n", altexec, strerror(errno));
- }
-
- while ((c = getopt(argc, argv, ":l:L:o:givs")) != EOF) {
- switch (c) {
- case 'l':
- label = optarg;
- break;
- case 'L':
- if ((label = getenv(optarg)) == NULL)
- label = CTF_DEFAULT_LABEL;
- break;
- case 'o':
- outfile = optarg;
- break;
- case 's':
- dynsym = CTF_USE_DYNSYM;
- break;
- case 'i':
- ignore_non_c = 1;
- break;
- case 'v':
- verbose = 1;
- break;
- default:
- usage();
- exit(2);
- }
- }
-
- if (argc - optind != 1 || label == NULL) {
- usage();
- exit(2);
- }
-
- infile = argv[optind];
- if (access(infile, R_OK) != 0)
- terminate("Can't access %s", infile);
-
- /*
- * Upon receipt of a signal, we want to clean up and exit. Our
- * primary goal during cleanup is to restore the system to a state
- * such that a subsequent make will eventually cause this command to
- * be re-run. If we remove the input file (which we do if we get a
- * signal and the user didn't specify a separate output file), make
- * will need to rebuild the input file, and will then need to re-run
- * ctfconvert, which is what we want.
- */
- set_terminate_cleanup(terminate_cleanup);
-
- sigset(SIGINT, handle_sig);
- sigset(SIGQUIT, handle_sig);
- sigset(SIGTERM, handle_sig);
-
- filetd = tdata_new();
-
- if (!file_read(filetd, infile, ignore_non_c))
- terminate("%s doesn't have type data to convert\n", infile);
-
- if (verbose)
- iidesc_stats(filetd->td_iihash);
-
- mstrtd = tdata_new();
- merge_into_master(filetd, mstrtd, NULL, 1);
-
- tdata_label_add(mstrtd, label, CTF_LABEL_LASTIDX);
-
- /*
- * If the user supplied an output file that is different from the
- * input file, write directly to the output file. Otherwise, write
- * to a temporary file, and replace the input file when we're done.
- */
- if (outfile && strcmp(infile, outfile) != 0) {
- write_ctf(mstrtd, infile, outfile, dynsym);
- } else {
- char *tmpname = mktmpname(infile, ".ctf");
-
- write_ctf(mstrtd, infile, tmpname, dynsym);
- if (rename(tmpname, infile) != 0)
- terminate("Couldn't rename temp file %s", tmpname);
- free(tmpname);
- }
-
- return (0);
-}
diff --git a/usr/src/tools/ctf/cvt/ctfmerge.c b/usr/src/tools/ctf/cvt/ctfmerge.c
deleted file mode 100644
index d2db789e5f..0000000000
--- a/usr/src/tools/ctf/cvt/ctfmerge.c
+++ /dev/null
@@ -1,1004 +0,0 @@
-/*
- * 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 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * Given several files containing CTF data, merge and uniquify that data into
- * a single CTF section in an output file.
- *
- * Merges can proceed independently. As such, we perform the merges in parallel
- * using a worker thread model. A given glob of CTF data (either all of the CTF
- * data from a single input file, or the result of one or more merges) can only
- * be involved in a single merge at any given time, so the process decreases in
- * parallelism, especially towards the end, as more and more files are
- * consolidated, finally resulting in a single merge of two large CTF graphs.
- * Unfortunately, the last merge is also the slowest, as the two graphs being
- * merged are each the product of merges of half of the input files.
- *
- * The algorithm consists of two phases, described in detail below. The first
- * phase entails the merging of CTF data in groups of eight. The second phase
- * takes the results of Phase I, and merges them two at a time. This disparity
- * is due to an observation that the merge time increases at least quadratically
- * with the size of the CTF data being merged. As such, merges of CTF graphs
- * newly read from input files are much faster than merges of CTF graphs that
- * are themselves the results of prior merges.
- *
- * A further complication is the need to ensure the repeatability of CTF merges.
- * That is, a merge should produce the same output every time, given the same
- * input. In both phases, this consistency requirement is met by imposing an
- * ordering on the merge process, thus ensuring that a given set of input files
- * are merged in the same order every time.
- *
- * Phase I
- *
- * The main thread reads the input files one by one, transforming the CTF
- * data they contain into tdata structures. When a given file has been read
- * and parsed, it is placed on the work queue for retrieval by worker threads.
- *
- * Central to Phase I is the Work In Progress (wip) array, which is used to
- * merge batches of files in a predictable order. Files are read by the main
- * thread, and are merged into wip array elements in round-robin order. When
- * the number of files merged into a given array slot equals the batch size,
- * the merged CTF graph in that array is added to the done slot in order by
- * array slot.
- *
- * For example, consider a case where we have five input files, a batch size
- * of two, a wip array size of two, and two worker threads (T1 and T2).
- *
- * 1. The wip array elements are assigned initial batch numbers 0 and 1.
- * 2. T1 reads an input file from the input queue (wq_queue). This is the
- * first input file, so it is placed into wip[0]. The second file is
- * similarly read and placed into wip[1]. The wip array slots now contain
- * one file each (wip_nmerged == 1).
- * 3. T1 reads the third input file, which it merges into wip[0]. The
- * number of files in wip[0] is equal to the batch size.
- * 4. T2 reads the fourth input file, which it merges into wip[1]. wip[1]
- * is now full too.
- * 5. T2 attempts to place the contents of wip[1] on the done queue
- * (wq_done_queue), but it can't, since the batch ID for wip[1] is 1.
- * Batch 0 needs to be on the done queue before batch 1 can be added, so
- * T2 blocks on wip[1]'s cv.
- * 6. T1 attempts to place the contents of wip[0] on the done queue, and
- * succeeds, updating wq_lastdonebatch to 0. It clears wip[0], and sets
- * its batch ID to 2. T1 then signals wip[1]'s cv to awaken T2.
- * 7. T2 wakes up, notices that wq_lastdonebatch is 0, which means that
- * batch 1 can now be added. It adds wip[1] to the done queue, clears
- * wip[1], and sets its batch ID to 3. It signals wip[0]'s cv, and
- * restarts.
- *
- * The above process continues until all input files have been consumed. At
- * this point, a pair of barriers are used to allow a single thread to move
- * any partial batches from the wip array to the done array in batch ID order.
- * When this is complete, wq_done_queue is moved to wq_queue, and Phase II
- * begins.
- *
- * Locking Semantics (Phase I)
- *
- * The input queue (wq_queue) and the done queue (wq_done_queue) are
- * protected by separate mutexes - wq_queue_lock and wq_done_queue. wip
- * array slots are protected by their own mutexes, which must be grabbed
- * before releasing the input queue lock. The wip array lock is dropped
- * when the thread restarts the loop. If the array slot was full, the
- * array lock will be held while the slot contents are added to the done
- * queue. The done queue lock is used to protect the wip slot cv's.
- *
- * The pow number is protected by the queue lock. The master batch ID
- * and last completed batch (wq_lastdonebatch) counters are protected *in
- * Phase I* by the done queue lock.
- *
- * Phase II
- *
- * When Phase II begins, the queue consists of the merged batches from the
- * first phase. Assume we have five batches:
- *
- * Q: a b c d e
- *
- * Using the same batch ID mechanism we used in Phase I, but without the wip
- * array, worker threads remove two entries at a time from the beginning of
- * the queue. These two entries are merged, and are added back to the tail
- * of the queue, as follows:
- *
- * Q: a b c d e # start
- * Q: c d e ab # a, b removed, merged, added to end
- * Q: e ab cd # c, d removed, merged, added to end
- * Q: cd eab # e, ab removed, merged, added to end
- * Q: cdeab # cd, eab removed, merged, added to end
- *
- * When one entry remains on the queue, with no merges outstanding, Phase II
- * finishes. We pre-determine the stopping point by pre-calculating the
- * number of nodes that will appear on the list. In the example above, the
- * number (wq_ninqueue) is 9. When ninqueue is 1, we conclude Phase II by
- * signaling the main thread via wq_done_cv.
- *
- * Locking Semantics (Phase II)
- *
- * The queue (wq_queue), ninqueue, and the master batch ID and last
- * completed batch counters are protected by wq_queue_lock. The done
- * queue and corresponding lock are unused in Phase II as is the wip array.
- *
- * Uniquification
- *
- * We want the CTF data that goes into a given module to be as small as
- * possible. For example, we don't want it to contain any type data that may
- * be present in another common module. As such, after creating the master
- * tdata_t for a given module, we can, if requested by the user, uniquify it
- * against the tdata_t from another module (genunix in the case of the SunOS
- * kernel). We perform a merge between the tdata_t for this module and the
- * tdata_t from genunix. Nodes found in this module that are not present in
- * genunix are added to a third tdata_t - the uniquified tdata_t.
- *
- * Additive Merges
- *
- * In some cases, for example if we are issuing a new version of a common
- * module in a patch, we need to make sure that the CTF data already present
- * in that module does not change. Changes to this data would void the CTF
- * data in any module that uniquified against the common module. To preserve
- * the existing data, we can perform what is known as an additive merge. In
- * this case, a final uniquification is performed against the CTF data in the
- * previous version of the module. The result will be the placement of new
- * and changed data after the existing data, thus preserving the existing type
- * ID space.
- *
- * Saving the result
- *
- * When the merges are complete, the resulting tdata_t is placed into the
- * output file, replacing the .SUNW_ctf section (if any) already in that file.
- *
- * The person who changes the merging thread code in this file without updating
- * this comment will not live to see the stock hit five.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <pthread.h>
-#include <assert.h>
-#include <synch.h>
-#include <signal.h>
-#include <libgen.h>
-#include <string.h>
-#include <errno.h>
-#include <alloca.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <sys/sysconf.h>
-
-#include "ctf_headers.h"
-#include "ctftools.h"
-#include "ctfmerge.h"
-#include "traverse.h"
-#include "memory.h"
-#include "fifo.h"
-#include "barrier.h"
-
-#pragma init(bigheap)
-
-#define MERGE_PHASE1_BATCH_SIZE 8
-#define MERGE_PHASE1_MAX_SLOTS 5
-#define MERGE_INPUT_THROTTLE_LEN 10
-
-const char *progname;
-static char *outfile = NULL;
-static char *tmpname = NULL;
-static int dynsym;
-int debug_level = DEBUG_LEVEL;
-static size_t maxpgsize = 0x400000;
-
-
-void
-usage(void)
-{
- (void) fprintf(stderr,
- "Usage: %s [-fstv] -l label | -L labelenv -o outfile file ...\n"
- " %s [-fstv] -l label | -L labelenv -o outfile -d uniqfile\n"
- " %*s [-D uniqlabel] file ...\n"
- " %s [-fstv] -l label | -L labelenv -o outfile -w withfile "
- "file ...\n"
- " %s -c srcfile destfile\n"
- "\n"
- " Note: if -L labelenv is specified and labelenv is not set in\n"
- " the environment, a default value is used.\n",
- progname, progname, strlen(progname), " ",
- progname, progname);
-}
-
-static void
-bigheap(void)
-{
- size_t big, *size;
- int sizes;
- struct memcntl_mha mha;
-
- /*
- * First, get the available pagesizes.
- */
- if ((sizes = getpagesizes(NULL, 0)) == -1)
- return;
-
- if (sizes == 1 || (size = alloca(sizeof (size_t) * sizes)) == NULL)
- return;
-
- if (getpagesizes(size, sizes) == -1)
- return;
-
- while (size[sizes - 1] > maxpgsize)
- sizes--;
-
- /* set big to the largest allowed page size */
- big = size[sizes - 1];
- if (big & (big - 1)) {
- /*
- * The largest page size is not a power of two for some
- * inexplicable reason; return.
- */
- return;
- }
-
- /*
- * Now, align our break to the largest page size.
- */
- if (brk((void *)((((uintptr_t)sbrk(0) - 1) & ~(big - 1)) + big)) != 0)
- return;
-
- /*
- * set the preferred page size for the heap
- */
- mha.mha_cmd = MHA_MAPSIZE_BSSBRK;
- mha.mha_flags = 0;
- mha.mha_pagesize = big;
-
- (void) memcntl(NULL, 0, MC_HAT_ADVISE, (caddr_t)&mha, 0, 0);
-}
-
-static void
-finalize_phase_one(workqueue_t *wq)
-{
- int startslot, i;
-
- /*
- * wip slots are cleared out only when maxbatchsz td's have been merged
- * into them. We're not guaranteed that the number of files we're
- * merging is a multiple of maxbatchsz, so there will be some partial
- * groups in the wip array. Move them to the done queue in batch ID
- * order, starting with the slot containing the next batch that would
- * have been placed on the done queue, followed by the others.
- * One thread will be doing this while the others wait at the barrier
- * back in worker_thread(), so we don't need to worry about pesky things
- * like locks.
- */
-
- for (startslot = -1, i = 0; i < wq->wq_nwipslots; i++) {
- if (wq->wq_wip[i].wip_batchid == wq->wq_lastdonebatch + 1) {
- startslot = i;
- break;
- }
- }
-
- assert(startslot != -1);
-
- for (i = startslot; i < startslot + wq->wq_nwipslots; i++) {
- int slotnum = i % wq->wq_nwipslots;
- wip_t *wipslot = &wq->wq_wip[slotnum];
-
- if (wipslot->wip_td != NULL) {
- debug(2, "clearing slot %d (%d) (saving %d)\n",
- slotnum, i, wipslot->wip_nmerged);
- } else
- debug(2, "clearing slot %d (%d)\n", slotnum, i);
-
- if (wipslot->wip_td != NULL) {
- fifo_add(wq->wq_donequeue, wipslot->wip_td);
- wq->wq_wip[slotnum].wip_td = NULL;
- }
- }
-
- wq->wq_lastdonebatch = wq->wq_next_batchid++;
-
- debug(2, "phase one done: donequeue has %d items\n",
- fifo_len(wq->wq_donequeue));
-}
-
-static void
-init_phase_two(workqueue_t *wq)
-{
- int num;
-
- /*
- * We're going to continually merge the first two entries on the queue,
- * placing the result on the end, until there's nothing left to merge.
- * At that point, everything will have been merged into one. The
- * initial value of ninqueue needs to be equal to the total number of
- * entries that will show up on the queue, both at the start of the
- * phase and as generated by merges during the phase.
- */
- wq->wq_ninqueue = num = fifo_len(wq->wq_donequeue);
- while (num != 1) {
- wq->wq_ninqueue += num / 2;
- num = num / 2 + num % 2;
- }
-
- /*
- * Move the done queue to the work queue. We won't be using the done
- * queue in phase 2.
- */
- assert(fifo_len(wq->wq_queue) == 0);
- fifo_free(wq->wq_queue, NULL);
- wq->wq_queue = wq->wq_donequeue;
-}
-
-static void
-wip_save_work(workqueue_t *wq, wip_t *slot, int slotnum)
-{
- pthread_mutex_lock(&wq->wq_donequeue_lock);
-
- while (wq->wq_lastdonebatch + 1 < slot->wip_batchid)
- pthread_cond_wait(&slot->wip_cv, &wq->wq_donequeue_lock);
- assert(wq->wq_lastdonebatch + 1 == slot->wip_batchid);
-
- fifo_add(wq->wq_donequeue, slot->wip_td);
- wq->wq_lastdonebatch++;
- pthread_cond_signal(&wq->wq_wip[(slotnum + 1) %
- wq->wq_nwipslots].wip_cv);
-
- /* reset the slot for next use */
- slot->wip_td = NULL;
- slot->wip_batchid = wq->wq_next_batchid++;
-
- pthread_mutex_unlock(&wq->wq_donequeue_lock);
-}
-
-static void
-wip_add_work(wip_t *slot, tdata_t *pow)
-{
- if (slot->wip_td == NULL) {
- slot->wip_td = pow;
- slot->wip_nmerged = 1;
- } else {
- debug(2, "%d: merging %p into %p\n", pthread_self(),
- (void *)pow, (void *)slot->wip_td);
-
- merge_into_master(pow, slot->wip_td, NULL, 0);
- tdata_free(pow);
-
- slot->wip_nmerged++;
- }
-}
-
-static void
-worker_runphase1(workqueue_t *wq)
-{
- wip_t *wipslot;
- tdata_t *pow;
- int wipslotnum, pownum;
-
- for (;;) {
- pthread_mutex_lock(&wq->wq_queue_lock);
-
- while (fifo_empty(wq->wq_queue)) {
- if (wq->wq_nomorefiles == 1) {
- pthread_cond_broadcast(&wq->wq_work_avail);
- pthread_mutex_unlock(&wq->wq_queue_lock);
-
- /* on to phase 2 ... */
- return;
- }
-
- pthread_cond_wait(&wq->wq_work_avail,
- &wq->wq_queue_lock);
- }
-
- /* there's work to be done! */
- pow = fifo_remove(wq->wq_queue);
- pownum = wq->wq_nextpownum++;
- pthread_cond_broadcast(&wq->wq_work_removed);
-
- assert(pow != NULL);
-
- /* merge it into the right slot */
- wipslotnum = pownum % wq->wq_nwipslots;
- wipslot = &wq->wq_wip[wipslotnum];
-
- pthread_mutex_lock(&wipslot->wip_lock);
-
- pthread_mutex_unlock(&wq->wq_queue_lock);
-
- wip_add_work(wipslot, pow);
-
- if (wipslot->wip_nmerged == wq->wq_maxbatchsz)
- wip_save_work(wq, wipslot, wipslotnum);
-
- pthread_mutex_unlock(&wipslot->wip_lock);
- }
-}
-
-static void
-worker_runphase2(workqueue_t *wq)
-{
- tdata_t *pow1, *pow2;
- int batchid;
-
- for (;;) {
- pthread_mutex_lock(&wq->wq_queue_lock);
-
- if (wq->wq_ninqueue == 1) {
- pthread_cond_broadcast(&wq->wq_work_avail);
- pthread_mutex_unlock(&wq->wq_queue_lock);
-
- debug(2, "%d: entering p2 completion barrier\n",
- pthread_self());
- if (barrier_wait(&wq->wq_bar1)) {
- pthread_mutex_lock(&wq->wq_queue_lock);
- wq->wq_alldone = 1;
- pthread_cond_signal(&wq->wq_alldone_cv);
- pthread_mutex_unlock(&wq->wq_queue_lock);
- }
-
- return;
- }
-
- if (fifo_len(wq->wq_queue) < 2) {
- pthread_cond_wait(&wq->wq_work_avail,
- &wq->wq_queue_lock);
- pthread_mutex_unlock(&wq->wq_queue_lock);
- continue;
- }
-
- /* there's work to be done! */
- pow1 = fifo_remove(wq->wq_queue);
- pow2 = fifo_remove(wq->wq_queue);
- wq->wq_ninqueue -= 2;
-
- batchid = wq->wq_next_batchid++;
-
- pthread_mutex_unlock(&wq->wq_queue_lock);
-
- debug(2, "%d: merging %p into %p\n", pthread_self(),
- (void *)pow1, (void *)pow2);
- merge_into_master(pow1, pow2, NULL, 0);
- tdata_free(pow1);
-
- /*
- * merging is complete. place at the tail of the queue in
- * proper order.
- */
- pthread_mutex_lock(&wq->wq_queue_lock);
- while (wq->wq_lastdonebatch + 1 != batchid) {
- pthread_cond_wait(&wq->wq_done_cv,
- &wq->wq_queue_lock);
- }
-
- wq->wq_lastdonebatch = batchid;
-
- fifo_add(wq->wq_queue, pow2);
- debug(2, "%d: added %p to queue, len now %d, ninqueue %d\n",
- pthread_self(), (void *)pow2, fifo_len(wq->wq_queue),
- wq->wq_ninqueue);
- pthread_cond_broadcast(&wq->wq_done_cv);
- pthread_cond_signal(&wq->wq_work_avail);
- pthread_mutex_unlock(&wq->wq_queue_lock);
- }
-}
-
-/*
- * Main loop for worker threads.
- */
-static void *
-worker_thread(void *ptr)
-{
- workqueue_t *wq = ptr;
-
- worker_runphase1(wq);
-
- debug(2, "%d: entering first barrier\n", pthread_self());
-
- if (barrier_wait(&wq->wq_bar1)) {
-
- debug(2, "%d: doing work in first barrier\n", pthread_self());
-
- finalize_phase_one(wq);
-
- init_phase_two(wq);
-
- debug(2, "%d: ninqueue is %d, %d on queue\n", pthread_self(),
- wq->wq_ninqueue, fifo_len(wq->wq_queue));
- }
-
- debug(2, "%d: entering second barrier\n", pthread_self());
-
- (void) barrier_wait(&wq->wq_bar2);
-
- debug(2, "%d: phase 1 complete\n", pthread_self());
-
- worker_runphase2(wq);
- return (NULL);
-}
-
-/*
- * Pass a tdata_t tree, built from an input file, off to the work queue for
- * consumption by worker threads.
- */
-static int
-merge_ctf_cb(tdata_t *td, char *name, void *arg)
-{
- workqueue_t *wq = arg;
-
- debug(3, "Adding tdata %p for processing\n", (void *)td);
-
- pthread_mutex_lock(&wq->wq_queue_lock);
- while (fifo_len(wq->wq_queue) > wq->wq_ithrottle) {
- debug(2, "Throttling input (len = %d, throttle = %d)\n",
- fifo_len(wq->wq_queue), wq->wq_ithrottle);
- pthread_cond_wait(&wq->wq_work_removed, &wq->wq_queue_lock);
- }
-
- fifo_add(wq->wq_queue, td);
- debug(1, "Thread %d announcing %s\n", pthread_self(), name);
- pthread_cond_broadcast(&wq->wq_work_avail);
- pthread_mutex_unlock(&wq->wq_queue_lock);
-
- return (1);
-}
-
-/*
- * This program is intended to be invoked from a Makefile, as part of the build.
- * As such, in the event of a failure or user-initiated interrupt (^C), we need
- * to ensure that a subsequent re-make will cause ctfmerge to be executed again.
- * Unfortunately, ctfmerge will usually be invoked directly after (and as part
- * of the same Makefile rule as) a link, and will operate on the linked file
- * in place. If we merely exit upon receipt of a SIGINT, a subsequent make
- * will notice that the *linked* file is newer than the object files, and thus
- * will not reinvoke ctfmerge. The only way to ensure that a subsequent make
- * reinvokes ctfmerge, is to remove the file to which we are adding CTF
- * data (confusingly named the output file). This means that the link will need
- * to happen again, but links are generally fast, and we can't allow the merge
- * to be skipped.
- *
- * Another possibility would be to block SIGINT entirely - to always run to
- * completion. The run time of ctfmerge can, however, be measured in minutes
- * in some cases, so this is not a valid option.
- */
-static void
-handle_sig(int sig)
-{
- terminate("Caught signal %d - exiting\n", sig);
-}
-
-static void
-terminate_cleanup(void)
-{
- int dounlink = getenv("CTFMERGE_TERMINATE_NO_UNLINK") ? 0 : 1;
-
- if (tmpname != NULL && dounlink)
- unlink(tmpname);
-
- if (outfile == NULL)
- return;
-
- if (dounlink) {
- fprintf(stderr, "Removing %s\n", outfile);
- unlink(outfile);
- }
-}
-
-static void
-copy_ctf_data(char *srcfile, char *destfile)
-{
- tdata_t *srctd;
-
- if (read_ctf(&srcfile, 1, NULL, read_ctf_save_cb, &srctd, 1) == 0)
- terminate("No CTF data found in source file %s\n", srcfile);
-
- tmpname = mktmpname(destfile, ".ctf");
- write_ctf(srctd, destfile, tmpname, CTF_COMPRESS);
- if (rename(tmpname, destfile) != 0) {
- terminate("Couldn't rename temp file %s to %s", tmpname,
- destfile);
- }
- free(tmpname);
- tdata_free(srctd);
-}
-
-static void
-wq_init(workqueue_t *wq, int nfiles)
-{
- int throttle, nslots, i;
-
- if (getenv("CTFMERGE_MAX_SLOTS"))
- nslots = atoi(getenv("CTFMERGE_MAX_SLOTS"));
- else
- nslots = MERGE_PHASE1_MAX_SLOTS;
-
- if (getenv("CTFMERGE_PHASE1_BATCH_SIZE"))
- wq->wq_maxbatchsz = atoi(getenv("CTFMERGE_PHASE1_BATCH_SIZE"));
- else
- wq->wq_maxbatchsz = MERGE_PHASE1_BATCH_SIZE;
-
- nslots = MIN(nslots, (nfiles + wq->wq_maxbatchsz - 1) /
- wq->wq_maxbatchsz);
-
- wq->wq_wip = xcalloc(sizeof (wip_t) * nslots);
- wq->wq_nwipslots = nslots;
- wq->wq_nthreads = MIN(sysconf(_SC_NPROCESSORS_ONLN) * 3 / 2, nslots);
- wq->wq_thread = xmalloc(sizeof (pthread_t) * wq->wq_nthreads);
-
- if (getenv("CTFMERGE_INPUT_THROTTLE"))
- throttle = atoi(getenv("CTFMERGE_INPUT_THROTTLE"));
- else
- throttle = MERGE_INPUT_THROTTLE_LEN;
- wq->wq_ithrottle = throttle * wq->wq_nthreads;
-
- debug(1, "Using %d slots, %d threads\n", wq->wq_nwipslots,
- wq->wq_nthreads);
-
- wq->wq_next_batchid = 0;
-
- for (i = 0; i < nslots; i++) {
- pthread_mutex_init(&wq->wq_wip[i].wip_lock, NULL);
- wq->wq_wip[i].wip_batchid = wq->wq_next_batchid++;
- }
-
- pthread_mutex_init(&wq->wq_queue_lock, NULL);
- wq->wq_queue = fifo_new();
- pthread_cond_init(&wq->wq_work_avail, NULL);
- pthread_cond_init(&wq->wq_work_removed, NULL);
- wq->wq_ninqueue = nfiles;
- wq->wq_nextpownum = 0;
-
- pthread_mutex_init(&wq->wq_donequeue_lock, NULL);
- wq->wq_donequeue = fifo_new();
- wq->wq_lastdonebatch = -1;
-
- pthread_cond_init(&wq->wq_done_cv, NULL);
-
- pthread_cond_init(&wq->wq_alldone_cv, NULL);
- wq->wq_alldone = 0;
-
- barrier_init(&wq->wq_bar1, wq->wq_nthreads);
- barrier_init(&wq->wq_bar2, wq->wq_nthreads);
-
- wq->wq_nomorefiles = 0;
-}
-
-static void
-start_threads(workqueue_t *wq)
-{
- sigset_t sets;
- int i;
-
- sigemptyset(&sets);
- sigaddset(&sets, SIGINT);
- sigaddset(&sets, SIGQUIT);
- sigaddset(&sets, SIGTERM);
- pthread_sigmask(SIG_BLOCK, &sets, NULL);
-
- for (i = 0; i < wq->wq_nthreads; i++) {
- pthread_create(&wq->wq_thread[i], NULL,
- worker_thread, wq);
- }
-
- sigset(SIGINT, handle_sig);
- sigset(SIGQUIT, handle_sig);
- sigset(SIGTERM, handle_sig);
- pthread_sigmask(SIG_UNBLOCK, &sets, NULL);
-}
-
-static void
-join_threads(workqueue_t *wq)
-{
- int i;
-
- for (i = 0; i < wq->wq_nthreads; i++) {
- pthread_join(wq->wq_thread[i], NULL);
- }
-}
-
-static int
-strcompare(const void *p1, const void *p2)
-{
- char *s1 = *((char **)p1);
- char *s2 = *((char **)p2);
-
- return (strcmp(s1, s2));
-}
-
-/*
- * Core work queue structure; passed to worker threads on thread creation
- * as the main point of coordination. Allocate as a static structure; we
- * could have put this into a local variable in main, but passing a pointer
- * into your stack to another thread is fragile at best and leads to some
- * hard-to-debug failure modes.
- */
-static workqueue_t wq;
-
-int
-main(int argc, char **argv)
-{
- tdata_t *mstrtd, *savetd;
- char *uniqfile = NULL, *uniqlabel = NULL;
- char *withfile = NULL;
- char *label = NULL;
- char **ifiles, **tifiles;
- int verbose = 0, docopy = 0;
- int write_fuzzy_match = 0;
- int require_ctf = 0;
- int nifiles, nielems;
- int c, i, idx, tidx, err;
-
- progname = basename(argv[0]);
-
- ctf_altexec("CTFMERGE_ALTEXEC", argc, argv);
-
- if (getenv("CTFMERGE_DEBUG_LEVEL"))
- debug_level = atoi(getenv("CTFMERGE_DEBUG_LEVEL"));
-
- err = 0;
- while ((c = getopt(argc, argv, ":cd:D:fl:L:o:tvw:s")) != EOF) {
- switch (c) {
- case 'c':
- docopy = 1;
- break;
- case 'd':
- /* Uniquify against `uniqfile' */
- uniqfile = optarg;
- break;
- case 'D':
- /* Uniquify against label `uniqlabel' in `uniqfile' */
- uniqlabel = optarg;
- break;
- case 'f':
- write_fuzzy_match = CTF_FUZZY_MATCH;
- break;
- case 'l':
- /* Label merged types with `label' */
- label = optarg;
- break;
- case 'L':
- /* Label merged types with getenv(`label`) */
- if ((label = getenv(optarg)) == NULL)
- label = CTF_DEFAULT_LABEL;
- break;
- case 'o':
- /* Place merged types in CTF section in `outfile' */
- outfile = optarg;
- break;
- case 't':
- /* Insist *all* object files built from C have CTF */
- require_ctf = 1;
- break;
- case 'v':
- /* More debugging information */
- verbose = 1;
- break;
- case 'w':
- /* Additive merge with data from `withfile' */
- withfile = optarg;
- break;
- case 's':
- /* use the dynsym rather than the symtab */
- dynsym = CTF_USE_DYNSYM;
- break;
- default:
- usage();
- exit(2);
- }
- }
-
- /* Validate arguments */
- if (docopy) {
- if (uniqfile != NULL || uniqlabel != NULL || label != NULL ||
- outfile != NULL || withfile != NULL || dynsym != 0)
- err++;
-
- if (argc - optind != 2)
- err++;
- } else {
- if (uniqfile != NULL && withfile != NULL)
- err++;
-
- if (uniqlabel != NULL && uniqfile == NULL)
- err++;
-
- if (outfile == NULL || label == NULL)
- err++;
-
- if (argc - optind == 0)
- err++;
- }
-
- if (err) {
- usage();
- exit(2);
- }
-
- if (uniqfile && access(uniqfile, R_OK) != 0) {
- warning("Uniquification file %s couldn't be opened and "
- "will be ignored.\n", uniqfile);
- uniqfile = NULL;
- }
- if (withfile && access(withfile, R_OK) != 0) {
- warning("With file %s couldn't be opened and will be "
- "ignored.\n", withfile);
- withfile = NULL;
- }
- if (outfile && access(outfile, R_OK|W_OK) != 0)
- terminate("Cannot open output file %s for r/w", outfile);
-
- /*
- * This is ugly, but we don't want to have to have a separate tool
- * (yet) just for copying an ELF section with our specific requirements,
- * so we shoe-horn a copier into ctfmerge.
- */
- if (docopy) {
- copy_ctf_data(argv[optind], argv[optind + 1]);
-
- exit(0);
- }
-
- set_terminate_cleanup(terminate_cleanup);
-
- /* Sort the input files and strip out duplicates */
- nifiles = argc - optind;
- ifiles = xmalloc(sizeof (char *) * nifiles);
- tifiles = xmalloc(sizeof (char *) * nifiles);
-
- for (i = 0; i < nifiles; i++)
- tifiles[i] = argv[optind + i];
- qsort(tifiles, nifiles, sizeof (char *), (int (*)())strcompare);
-
- ifiles[0] = tifiles[0];
- for (idx = 0, tidx = 1; tidx < nifiles; tidx++) {
- if (strcmp(ifiles[idx], tifiles[tidx]) != 0)
- ifiles[++idx] = tifiles[tidx];
- }
- nifiles = idx + 1;
-
- /* Make sure they all exist */
- if ((nielems = count_files(ifiles, nifiles)) < 0)
- terminate("Some input files were inaccessible\n");
-
- /* Prepare for the merge */
- wq_init(&wq, nielems);
-
- start_threads(&wq);
-
- /*
- * Start the merge
- *
- * We're reading everything from each of the object files, so we
- * don't need to specify labels.
- */
- if (read_ctf(ifiles, nifiles, NULL, merge_ctf_cb,
- &wq, require_ctf) == 0) {
- /*
- * If we're verifying that C files have CTF, it's safe to
- * assume that in this case, we're building only from assembly
- * inputs.
- */
- if (require_ctf)
- exit(0);
- terminate("No ctf sections found to merge\n");
- }
-
- pthread_mutex_lock(&wq.wq_queue_lock);
- wq.wq_nomorefiles = 1;
- pthread_cond_broadcast(&wq.wq_work_avail);
- pthread_mutex_unlock(&wq.wq_queue_lock);
-
- pthread_mutex_lock(&wq.wq_queue_lock);
- while (wq.wq_alldone == 0)
- pthread_cond_wait(&wq.wq_alldone_cv, &wq.wq_queue_lock);
- pthread_mutex_unlock(&wq.wq_queue_lock);
-
- join_threads(&wq);
-
- /*
- * All requested files have been merged, with the resulting tree in
- * mstrtd. savetd is the tree that will be placed into the output file.
- *
- * Regardless of whether we're doing a normal uniquification or an
- * additive merge, we need a type tree that has been uniquified
- * against uniqfile or withfile, as appropriate.
- *
- * If we're doing a uniquification, we stuff the resulting tree into
- * outfile. Otherwise, we add the tree to the tree already in withfile.
- */
- assert(fifo_len(wq.wq_queue) == 1);
- mstrtd = fifo_remove(wq.wq_queue);
-
- if (verbose || debug_level) {
- debug(2, "Statistics for td %p\n", (void *)mstrtd);
-
- iidesc_stats(mstrtd->td_iihash);
- }
-
- if (uniqfile != NULL || withfile != NULL) {
- char *reffile, *reflabel = NULL;
- tdata_t *reftd;
-
- if (uniqfile != NULL) {
- reffile = uniqfile;
- reflabel = uniqlabel;
- } else
- reffile = withfile;
-
- if (read_ctf(&reffile, 1, reflabel, read_ctf_save_cb,
- &reftd, require_ctf) == 0) {
- terminate("No CTF data found in reference file %s\n",
- reffile);
- }
-
- savetd = tdata_new();
-
- if (CTF_TYPE_ISCHILD(reftd->td_nextid))
- terminate("No room for additional types in master\n");
-
- savetd->td_nextid = withfile ? reftd->td_nextid :
- CTF_INDEX_TO_TYPE(1, TRUE);
- merge_into_master(mstrtd, reftd, savetd, 0);
-
- tdata_label_add(savetd, label, CTF_LABEL_LASTIDX);
-
- if (withfile) {
- /*
- * savetd holds the new data to be added to the withfile
- */
- tdata_t *withtd = reftd;
-
- tdata_merge(withtd, savetd);
-
- savetd = withtd;
- } else {
- char uniqname[MAXPATHLEN];
- labelent_t *parle;
-
- parle = tdata_label_top(reftd);
-
- savetd->td_parlabel = xstrdup(parle->le_name);
-
- strncpy(uniqname, reffile, sizeof (uniqname));
- uniqname[MAXPATHLEN - 1] = '\0';
- savetd->td_parname = xstrdup(basename(uniqname));
- }
-
- } else {
- /*
- * No post processing. Write the merged tree as-is into the
- * output file.
- */
- tdata_label_free(mstrtd);
- tdata_label_add(mstrtd, label, CTF_LABEL_LASTIDX);
-
- savetd = mstrtd;
- }
-
- tmpname = mktmpname(outfile, ".ctf");
- write_ctf(savetd, outfile, tmpname,
- CTF_COMPRESS | write_fuzzy_match | dynsym);
- if (rename(tmpname, outfile) != 0)
- terminate("Couldn't rename output temp file %s", tmpname);
- free(tmpname);
-
- return (0);
-}
diff --git a/usr/src/tools/ctf/cvt/ctfmerge.h b/usr/src/tools/ctf/cvt/ctfmerge.h
deleted file mode 100644
index ce40803d52..0000000000
--- a/usr/src/tools/ctf/cvt/ctfmerge.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _CTFMERGE_H
-#define _CTFMERGE_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Merging structures used in ctfmerge. See ctfmerge.c for locking semantics.
- */
-
-#include <pthread.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "ctftools.h"
-#include "barrier.h"
-#include "fifo.h"
-
-typedef struct wip {
- pthread_mutex_t wip_lock;
- pthread_cond_t wip_cv;
- tdata_t *wip_td;
- int wip_nmerged;
- int wip_batchid;
-} wip_t;
-
-typedef struct workqueue {
- int wq_next_batchid;
-
- int wq_maxbatchsz;
-
- wip_t *wq_wip;
- int wq_nwipslots;
- int wq_nthreads;
- int wq_ithrottle;
-
- pthread_mutex_t wq_queue_lock;
- fifo_t *wq_queue;
- pthread_cond_t wq_work_avail;
- pthread_cond_t wq_work_removed;
- int wq_ninqueue;
- int wq_nextpownum;
-
- pthread_mutex_t wq_donequeue_lock;
- fifo_t *wq_donequeue;
- int wq_lastdonebatch;
- pthread_cond_t wq_done_cv;
-
- pthread_cond_t wq_alldone_cv; /* protected by queue_lock */
- int wq_alldone;
-
- int wq_nomorefiles;
-
- pthread_t *wq_thread;
-
- barrier_t wq_bar1;
- barrier_t wq_bar2;
-} workqueue_t;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _CTFMERGE_H */
diff --git a/usr/src/tools/ctf/cvt/ctftools.h b/usr/src/tools/ctf/cvt/ctftools.h
deleted file mode 100644
index 7547ce389f..0000000000
--- a/usr/src/tools/ctf/cvt/ctftools.h
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef _CTFTOOLS_H
-#define _CTFTOOLS_H
-
-/*
- * Functions and data structures used in the manipulation of stabs and CTF data
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <libelf.h>
-#include <gelf.h>
-#include <pthread.h>
-
-#include <sys/ccompile.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "list.h"
-#include "hash.h"
-
-#ifndef DEBUG_LEVEL
-#define DEBUG_LEVEL 0
-#endif
-#ifndef DEBUG_PARSE
-#define DEBUG_PARSE 0
-#endif
-
-#ifndef DEBUG_STREAM
-#define DEBUG_STREAM stderr
-#endif
-
-#ifndef MAX
-#define MAX(a, b) ((a) < (b) ? (b) : (a))
-#endif
-
-#ifndef MIN
-#define MIN(a, b) ((a) > (b) ? (b) : (a))
-#endif
-
-#define TRUE 1
-#define FALSE 0
-
-#define CTF_ELF_SCN_NAME ".SUNW_ctf"
-
-#define CTF_LABEL_LASTIDX -1
-
-#define CTF_DEFAULT_LABEL "*** No Label Provided ***"
-
-/*
- * Default hash sizes
- */
-#define TDATA_LAYOUT_HASH_SIZE 8191 /* A tdesc hash based on layout */
-#define TDATA_ID_HASH_SIZE 997 /* A tdesc hash based on type id */
-#define IIDESC_HASH_SIZE 8191 /* Hash of iidesc's */
-
-/*
- * The default function argument array size. We'll realloc the array larger
- * if we need to, but we want a default value that will allow us to avoid
- * reallocation in the common case.
- */
-#define FUNCARG_DEF 5
-
-extern const char *progname;
-extern int debug_level;
-extern int debug_parse;
-extern const char *curhdr;
-
-/*
- * This is a partial copy of the stab.h that DevPro includes with their
- * compiler.
- */
-typedef struct stab {
- uint32_t n_strx;
- uint8_t n_type;
- int8_t n_other;
- int16_t n_desc;
- uint32_t n_value;
-} stab_t;
-
-#define N_GSYM 0x20 /* global symbol: name,,0,type,0 */
-#define N_FUN 0x24 /* procedure: name,,0,linenumber,0 */
-#define N_STSYM 0x26 /* static symbol: name,,0,type,0 or section relative */
-#define N_LCSYM 0x28 /* .lcomm symbol: name,,0,type,0 or section relative */
-#define N_ROSYM 0x2c /* ro_data: name,,0,type,0 or section relative */
-#define N_OPT 0x3c /* compiler options */
-#define N_RSYM 0x40 /* register sym: name,,0,type,register */
-#define N_SO 0x64 /* source file name: name,,0,0,0 */
-#define N_LSYM 0x80 /* local sym: name,,0,type,offset */
-#define N_SOL 0x84 /* #included file name: name,,0,0,0 */
-#define N_PSYM 0xa0 /* parameter: name,,0,type,offset */
-#define N_LBRAC 0xc0 /* left bracket: 0,,0,nesting level,function relative */
-#define N_RBRAC 0xe0 /* right bracket: 0,,0,nesting level,func relative */
-#define N_BINCL 0x82 /* header file: name,,0,0,0 */
-#define N_EINCL 0xa2 /* end of include file */
-
-/*
- * Nodes in the type tree
- *
- * Each node consists of a single tdesc_t, with one of several auxiliary
- * structures linked in via the `data' union.
- */
-
-/* The type of tdesc_t node */
-typedef enum stabtype {
- STABTYPE_FIRST, /* do not use */
- INTRINSIC,
- POINTER,
- ARRAY,
- FUNCTION,
- STRUCT,
- UNION,
- ENUM,
- FORWARD,
- TYPEDEF,
- TYPEDEF_UNRES,
- VOLATILE,
- CONST,
- RESTRICT,
- STABTYPE_LAST /* do not use */
-} stabtype_t;
-
-typedef struct tdesc tdesc_t;
-
-/* Auxiliary structure for array tdesc_t */
-typedef struct ardef {
- tdesc_t *ad_contents;
- tdesc_t *ad_idxtype;
- uint_t ad_nelems;
-} ardef_t;
-
-/* Auxiliary structure for structure/union tdesc_t */
-typedef struct mlist {
- int ml_offset; /* Offset from start of structure (in bits) */
- int ml_size; /* Member size (in bits) */
- char *ml_name; /* Member name */
- struct tdesc *ml_type; /* Member type */
- struct mlist *ml_next; /* Next member */
-} mlist_t;
-
-/* Auxiliary structure for enum tdesc_t */
-typedef struct elist {
- char *el_name;
- int el_number;
- struct elist *el_next;
-} elist_t;
-
-/* Auxiliary structure for intrinsics (integers and reals) */
-typedef enum {
- INTR_INT,
- INTR_REAL
-} intrtype_t;
-
-typedef struct intr {
- intrtype_t intr_type;
- int intr_signed;
- union {
- char _iformat;
- int _fformat;
- } _u;
- int intr_offset;
- int intr_nbits;
-} intr_t;
-
-#define intr_iformat _u._iformat
-#define intr_fformat _u._fformat
-
-typedef struct fnarg {
- char *fna_name;
- struct tdesc *fna_type;
-} fnarg_t;
-
-#define FN_F_GLOBAL 0x1
-#define FN_F_VARARGS 0x2
-
-typedef struct fndef {
- struct tdesc *fn_ret;
- uint_t fn_nargs;
- tdesc_t **fn_args;
- uint_t fn_vargs;
-} fndef_t;
-
-typedef int32_t tid_t;
-
-/*
- * The tdesc_t (Type DESCription) is the basic node type used in the stabs data
- * structure. Each data node gets a tdesc structure. Each node is linked into
- * a directed graph (think of it as a tree with multiple roots and multiple
- * leaves), with the root nodes at the top, and intrinsics at the bottom. The
- * root nodes, which are pointed to by iidesc nodes, correspond to the types,
- * globals, and statics defined by the stabs.
- */
-struct tdesc {
- char *t_name;
- tdesc_t *t_next; /* Name hash next pointer */
-
- tid_t t_id;
- tdesc_t *t_hash; /* ID hash next pointer */
-
- stabtype_t t_type;
- int t_size; /* Size in bytes of object represented by this node */
-
- union {
- intr_t *intr; /* int, real */
- tdesc_t *tdesc; /* ptr, typedef, vol, const, restr */
- ardef_t *ardef; /* array */
- mlist_t *members; /* struct, union */
- elist_t *emem; /* enum */
- fndef_t *fndef; /* function - first is return type */
- } t_data;
-
- int t_flags;
- int t_vgen; /* Visitation generation (see traverse.c) */
- int t_emark; /* Equality mark (see equiv_cb() in merge.c) */
-};
-
-#define t_intr t_data.intr
-#define t_tdesc t_data.tdesc
-#define t_ardef t_data.ardef
-#define t_members t_data.members
-#define t_emem t_data.emem
-#define t_fndef t_data.fndef
-
-#define TDESC_F_ISROOT 0x1 /* Has an iidesc_t (see below) */
-#define TDESC_F_GLOBAL 0x2
-#define TDESC_F_RESOLVED 0x4
-
-/*
- * iidesc_t (Interesting Item DESCription) nodes point to tdesc_t nodes that
- * correspond to "interesting" stabs. A stab is interesting if it defines a
- * global or static variable, a global or static function, or a data type.
- */
-typedef enum iitype {
- II_NOT = 0,
- II_GFUN, /* Global function */
- II_SFUN, /* Static function */
- II_GVAR, /* Global variable */
- II_SVAR, /* Static variable */
- II_PSYM, /* Function argument */
- II_SOU, /* Struct or union */
- II_TYPE /* Type (typedef) */
-} iitype_t;
-
-typedef struct iidesc {
- iitype_t ii_type;
- char *ii_name;
- tdesc_t *ii_dtype;
- char *ii_owner; /* File that defined this node */
- int ii_flags;
-
- /* Function arguments (if any) */
- int ii_nargs;
- tdesc_t **ii_args;
- int ii_vargs; /* Function uses varargs */
-} iidesc_t;
-
-#define IIDESC_F_USED 0x1 /* Write this iidesc out */
-
-/*
- * labelent_t nodes identify labels and corresponding type ranges associated
- * with them. The label in a given labelent_t is associated with types with
- * ids <= le_idx.
- */
-typedef struct labelent {
- char *le_name;
- int le_idx;
-} labelent_t;
-
-/*
- * The tdata_t (Type DATA) structure contains or references all type data for
- * a given file or, during merging, several files.
- */
-typedef struct tdata {
- int td_curemark; /* Equality mark (see merge.c) */
- int td_curvgen; /* Visitation generation (see traverse.c) */
- int td_nextid; /* The ID for the next tdesc_t created */
- hash_t *td_iihash; /* The iidesc_t nodes for this file */
-
- hash_t *td_layouthash; /* The tdesc nodes, hashed by structure */
- hash_t *td_idhash; /* The tdesc nodes, hashed by type id */
- list_t *td_fwdlist; /* All forward declaration tdesc nodes */
-
- char *td_parlabel; /* Top label uniq'd against in parent */
- char *td_parname; /* Basename of parent */
- list_t *td_labels; /* Labels and their type ranges */
-
- pthread_mutex_t td_mergelock;
-
- int td_ref;
-} tdata_t;
-
-/*
- * By design, the iidesc hash is heterogeneous. The CTF emitter, on the
- * other hand, needs to be able to access the elements of the list by type,
- * and in a specific sorted order. An iiburst holds these elements in that
- * order. (A burster is a machine that separates carbon-copy forms)
- */
-typedef struct iiburst {
- int iib_nfuncs;
- int iib_curfunc;
- iidesc_t **iib_funcs;
-
- int iib_nobjts;
- int iib_curobjt;
- iidesc_t **iib_objts;
-
- list_t *iib_types;
- int iib_maxtypeid;
-
- tdata_t *iib_td;
- struct tdtrav_data *iib_tdtd; /* tdtrav_data_t */
-} iiburst_t;
-
-typedef struct ctf_buf ctf_buf_t;
-
-typedef struct symit_data symit_data_t;
-
-/* fixup_tdescs.c */
-void cvt_fixstabs(tdata_t *);
-void cvt_fixups(tdata_t *, size_t);
-
-/* ctf.c */
-caddr_t ctf_gen(iiburst_t *, size_t *, int);
-tdata_t *ctf_load(char *, caddr_t, size_t, symit_data_t *, char *);
-
-/* iidesc.c */
-iidesc_t *iidesc_new(char *);
-int iidesc_hash(int, void *);
-void iter_iidescs_by_name(tdata_t *, const char *,
- int (*)(iidesc_t *, void *), void *);
-iidesc_t *iidesc_dup(iidesc_t *);
-iidesc_t *iidesc_dup_rename(iidesc_t *, char const *, char const *);
-void iidesc_add(hash_t *, iidesc_t *);
-void iidesc_free(iidesc_t *);
-void iidesc_free_cb(void *, void *);
-int iidesc_count_type(void *, void *);
-void iidesc_stats(hash_t *);
-int iidesc_dump(iidesc_t *);
-
-/* input.c */
-typedef enum source_types {
- SOURCE_NONE = 0,
- SOURCE_UNKNOWN = 1,
- SOURCE_C = 2,
- SOURCE_S = 4
-} source_types_t;
-
-source_types_t built_source_types(Elf *, const char *);
-int count_files(char **, int);
-int read_ctf(char **, int, char *, int (*)(tdata_t *, char *, void *),
- void *, int);
-int read_ctf_save_cb(tdata_t *, char *, void *);
-symit_data_t *symit_new(Elf *, const char *);
-void symit_reset(symit_data_t *);
-char *symit_curfile(symit_data_t *);
-GElf_Sym *symit_next(symit_data_t *, int);
-char *symit_name(symit_data_t *);
-void symit_free(symit_data_t *);
-
-/* merge.c */
-void merge_into_master(tdata_t *, tdata_t *, tdata_t *, int);
-
-/* output.c */
-#define CTF_FUZZY_MATCH 0x1 /* match local symbols to global CTF */
-#define CTF_USE_DYNSYM 0x2 /* use .dynsym not .symtab */
-#define CTF_COMPRESS 0x4 /* compress CTF output */
-
-void write_ctf(tdata_t *, const char *, const char *, int);
-
-/* parse.c */
-void parse_init(tdata_t *);
-void parse_finish(tdata_t *);
-int parse_stab(stab_t *, char *, iidesc_t **);
-tdesc_t *lookup(int);
-tdesc_t *lookupname(const char *);
-void check_hash(void);
-void resolve_typed_bitfields(void);
-
-/* stabs.c */
-int stabs_read(tdata_t *, Elf *, const char *);
-
-/* dwarf.c */
-int dw_read(tdata_t *, Elf *, const char *);
-const char *dw_tag2str(uint_t);
-
-/* tdata.c */
-tdata_t *tdata_new(void);
-void tdata_free(tdata_t *);
-void tdata_build_hashes(tdata_t *td);
-const char *tdesc_name(tdesc_t *);
-int tdesc_idhash(int, void *);
-int tdesc_idcmp(void *, void *);
-int tdesc_namehash(int, void *);
-int tdesc_namecmp(void *, void *);
-int tdesc_layouthash(int, void *);
-int tdesc_layoutcmp(void *, void *);
-void tdesc_free(tdesc_t *);
-void tdata_label_add(tdata_t *, char *, int);
-labelent_t *tdata_label_top(tdata_t *);
-int tdata_label_find(tdata_t *, char *);
-void tdata_label_free(tdata_t *);
-void tdata_merge(tdata_t *, tdata_t *);
-void tdata_label_newmax(tdata_t *, int);
-
-/* util.c */
-int streq(const char *, const char *);
-int findelfsecidx(Elf *, const char *, const char *);
-size_t elf_ptrsz(Elf *);
-char *mktmpname(const char *, const char *);
-void terminate(char *, ...) __NORETURN;
-void aborterr(char *, ...) __NORETURN;
-void set_terminate_cleanup(void (*)());
-void elfterminate(const char *, const char *, ...);
-void warning(char *, ...);
-void vadebug(int, char *, va_list);
-void debug(int, char *, ...);
-
-/* altexec.c */
-void ctf_altexec(const char *, int argc, char **);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _CTFTOOLS_H */
diff --git a/usr/src/tools/ctf/cvt/dwarf.c b/usr/src/tools/ctf/cvt/dwarf.c
deleted file mode 100644
index afca423005..0000000000
--- a/usr/src/tools/ctf/cvt/dwarf.c
+++ /dev/null
@@ -1,2027 +0,0 @@
-/*
- * 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 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * Copyright 2012 Jason King. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * DWARF to tdata conversion
- *
- * For the most part, conversion is straightforward, proceeding in two passes.
- * On the first pass, we iterate through every die, creating new type nodes as
- * necessary. Referenced tdesc_t's are created in an uninitialized state, thus
- * allowing type reference pointers to be filled in. If the tdesc_t
- * corresponding to a given die can be completely filled out (sizes and offsets
- * calculated, and so forth) without using any referenced types, the tdesc_t is
- * marked as resolved. Consider an array type. If the type corresponding to
- * the array contents has not yet been processed, we will create a blank tdesc
- * for the contents type (only the type ID will be filled in, relying upon the
- * later portion of the first pass to encounter and complete the referenced
- * type). We will then attempt to determine the size of the array. If the
- * array has a byte size attribute, we will have completely characterized the
- * array type, and will be able to mark it as resolved. The lack of a byte
- * size attribute, on the other hand, will prevent us from fully resolving the
- * type, as the size will only be calculable with reference to the contents
- * type, which has not, as yet, been encountered. The array type will thus be
- * left without the resolved flag, and the first pass will continue.
- *
- * When we begin the second pass, we will have created tdesc_t nodes for every
- * type in the section. We will traverse the tree, from the iidescs down,
- * processing each unresolved node. As the referenced nodes will have been
- * populated, the array type used in our example above will be able to use the
- * size of the referenced types (if available) to determine its own type. The
- * traversal will be repeated until all types have been resolved or we have
- * failed to make progress. When all tdescs have been resolved, the conversion
- * is complete.
- *
- * There are, as always, a few special cases that are handled during the first
- * and second passes:
- *
- * 1. Empty enums - GCC will occasionally emit an enum without any members.
- * Later on in the file, it will emit the same enum type, though this time
- * with the full complement of members. All references to the memberless
- * enum need to be redirected to the full definition. During the first
- * pass, each enum is entered in dm_enumhash, along with a pointer to its
- * corresponding tdesc_t. If, during the second pass, we encounter a
- * memberless enum, we use the hash to locate the full definition. All
- * tdescs referencing the empty enum are then redirected.
- *
- * 2. Forward declarations - If the compiler sees a forward declaration for
- * a structure, followed by the definition of that structure, it will emit
- * DWARF data for both the forward declaration and the definition. We need
- * to resolve the forward declarations when possible, by redirecting
- * forward-referencing tdescs to the actual struct/union definitions. This
- * redirection is done completely within the first pass. We begin by
- * recording all forward declarations in dw_fwdhash. When we define a
- * structure, we check to see if there have been any corresponding forward
- * declarations. If so, we redirect the tdescs which referenced the forward
- * declarations to the structure or union definition.
- *
- * XXX see if a post traverser will allow the elimination of repeated pass 2
- * traversals.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <errno.h>
-#include <libelf.h>
-#include <libdwarf.h>
-#include <libgen.h>
-#include <dwarf.h>
-
-#include "ctf_headers.h"
-#include "ctftools.h"
-#include "memory.h"
-#include "list.h"
-#include "traverse.h"
-
-/* The version of DWARF which we support. */
-#define DWARF_VERSION 2
-
-/*
- * We need to define a couple of our own intrinsics, to smooth out some of the
- * differences between the GCC and DevPro DWARF emitters. See the referenced
- * routines and the special cases in the file comment for more details.
- *
- * Type IDs are 32 bits wide. We're going to use the top of that field to
- * indicate types that we've created ourselves.
- */
-#define TID_FILEMAX 0x3fffffff /* highest tid from file */
-#define TID_VOID 0x40000001 /* see die_void() */
-#define TID_LONG 0x40000002 /* see die_array() */
-
-#define TID_MFGTID_BASE 0x40000003 /* first mfg'd tid */
-
-/*
- * To reduce the staggering amount of error-handling code that would otherwise
- * be required, the attribute-retrieval routines handle most of their own
- * errors. If the following flag is supplied as the value of the `req'
- * argument, they will also handle the absence of a requested attribute by
- * terminating the program.
- */
-#define DW_ATTR_REQ 1
-
-#define TDESC_HASH_BUCKETS 511
-
-typedef struct dwarf {
- Dwarf_Debug dw_dw; /* for libdwarf */
- Dwarf_Error dw_err; /* for libdwarf */
- Dwarf_Unsigned dw_maxoff; /* highest legal offset in this cu */
- tdata_t *dw_td; /* root of the tdesc/iidesc tree */
- hash_t *dw_tidhash; /* hash of tdescs by t_id */
- hash_t *dw_fwdhash; /* hash of fwd decls by name */
- hash_t *dw_enumhash; /* hash of memberless enums by name */
- tdesc_t *dw_void; /* manufactured void type */
- tdesc_t *dw_long; /* manufactured long type for arrays */
- size_t dw_ptrsz; /* size of a pointer in this file */
- tid_t dw_mfgtid_last; /* last mfg'd type ID used */
- uint_t dw_nunres; /* count of unresolved types */
- char *dw_cuname; /* name of compilation unit */
-} dwarf_t;
-
-static void die_create_one(dwarf_t *, Dwarf_Die);
-static void die_create(dwarf_t *, Dwarf_Die);
-
-static tid_t
-mfgtid_next(dwarf_t *dw)
-{
- return (++dw->dw_mfgtid_last);
-}
-
-static void
-tdesc_add(dwarf_t *dw, tdesc_t *tdp)
-{
- hash_add(dw->dw_tidhash, tdp);
-}
-
-static tdesc_t *
-tdesc_lookup(dwarf_t *dw, int tid)
-{
- tdesc_t tmpl, *tdp;
-
- tmpl.t_id = tid;
-
- if (hash_find(dw->dw_tidhash, &tmpl, (void **)&tdp))
- return (tdp);
- else
- return (NULL);
-}
-
-/*
- * Resolve a tdesc down to a node which should have a size. Returns the size,
- * zero if the size hasn't yet been determined.
- */
-static size_t
-tdesc_size(tdesc_t *tdp)
-{
- for (;;) {
- switch (tdp->t_type) {
- case INTRINSIC:
- case POINTER:
- case ARRAY:
- case FUNCTION:
- case STRUCT:
- case UNION:
- case ENUM:
- return (tdp->t_size);
-
- case FORWARD:
- return (0);
-
- case TYPEDEF:
- case VOLATILE:
- case CONST:
- case RESTRICT:
- tdp = tdp->t_tdesc;
- continue;
-
- case 0: /* not yet defined */
- return (0);
-
- default:
- terminate("tdp %u: tdesc_size on unknown type %d\n",
- tdp->t_id, tdp->t_type);
- }
- }
-}
-
-static size_t
-tdesc_bitsize(tdesc_t *tdp)
-{
- for (;;) {
- switch (tdp->t_type) {
- case INTRINSIC:
- return (tdp->t_intr->intr_nbits);
-
- case ARRAY:
- case FUNCTION:
- case STRUCT:
- case UNION:
- case ENUM:
- case POINTER:
- return (tdp->t_size * NBBY);
-
- case FORWARD:
- return (0);
-
- case TYPEDEF:
- case VOLATILE:
- case RESTRICT:
- case CONST:
- tdp = tdp->t_tdesc;
- continue;
-
- case 0: /* not yet defined */
- return (0);
-
- default:
- terminate("tdp %u: tdesc_bitsize on unknown type %d\n",
- tdp->t_id, tdp->t_type);
- }
- }
-}
-
-static tdesc_t *
-tdesc_basetype(tdesc_t *tdp)
-{
- for (;;) {
- switch (tdp->t_type) {
- case TYPEDEF:
- case VOLATILE:
- case RESTRICT:
- case CONST:
- tdp = tdp->t_tdesc;
- break;
- case 0: /* not yet defined */
- return (NULL);
- default:
- return (tdp);
- }
- }
-}
-
-static Dwarf_Off
-die_off(dwarf_t *dw, Dwarf_Die die)
-{
- Dwarf_Off off;
-
- if (dwarf_dieoffset(die, &off, &dw->dw_err) == DW_DLV_OK)
- return (off);
-
- terminate("failed to get offset for die: %s\n",
- dwarf_errmsg(dw->dw_err));
- /*NOTREACHED*/
- return (0);
-}
-
-static Dwarf_Die
-die_sibling(dwarf_t *dw, Dwarf_Die die)
-{
- Dwarf_Die sib;
- int rc;
-
- if ((rc = dwarf_siblingof(dw->dw_dw, die, &sib, &dw->dw_err)) ==
- DW_DLV_OK)
- return (sib);
- else if (rc == DW_DLV_NO_ENTRY)
- return (NULL);
-
- terminate("die %llu: failed to find type sibling: %s\n",
- die_off(dw, die), dwarf_errmsg(dw->dw_err));
- /*NOTREACHED*/
- return (NULL);
-}
-
-static Dwarf_Die
-die_child(dwarf_t *dw, Dwarf_Die die)
-{
- Dwarf_Die child;
- int rc;
-
- if ((rc = dwarf_child(die, &child, &dw->dw_err)) == DW_DLV_OK)
- return (child);
- else if (rc == DW_DLV_NO_ENTRY)
- return (NULL);
-
- terminate("die %llu: failed to find type child: %s\n",
- die_off(dw, die), dwarf_errmsg(dw->dw_err));
- /*NOTREACHED*/
- return (NULL);
-}
-
-static Dwarf_Half
-die_tag(dwarf_t *dw, Dwarf_Die die)
-{
- Dwarf_Half tag;
-
- if (dwarf_tag(die, &tag, &dw->dw_err) == DW_DLV_OK)
- return (tag);
-
- terminate("die %llu: failed to get tag for type: %s\n",
- die_off(dw, die), dwarf_errmsg(dw->dw_err));
- /*NOTREACHED*/
- return (0);
-}
-
-static Dwarf_Attribute
-die_attr(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, int req)
-{
- Dwarf_Attribute attr;
- int rc;
-
- if ((rc = dwarf_attr(die, name, &attr, &dw->dw_err)) == DW_DLV_OK) {
- return (attr);
- } else if (rc == DW_DLV_NO_ENTRY) {
- if (req) {
- terminate("die %llu: no attr 0x%x\n", die_off(dw, die),
- name);
- } else {
- return (NULL);
- }
- }
-
- terminate("die %llu: failed to get attribute for type: %s\n",
- die_off(dw, die), dwarf_errmsg(dw->dw_err));
- /*NOTREACHED*/
- return (NULL);
-}
-
-static Dwarf_Half
-die_attr_form(dwarf_t *dw, Dwarf_Attribute attr)
-{
- Dwarf_Half form;
-
- if (dwarf_whatform(attr, &form, &dw->dw_err) == DW_DLV_OK)
- return (form);
-
- terminate("failed to get attribute form for type: %s\n",
- dwarf_errmsg(dw->dw_err));
- /*NOTREACHED*/
- return (0);
-}
-
-/*
- * the following functions lookup the value of an attribute in a DIE:
- *
- * die_signed
- * die_unsigned
- * die_bool
- * die_string
- *
- * They all take the same parameters (with the exception of valp which is
- * a pointer to the type of the attribute we are looking up):
- *
- * dw - the dwarf object to look in
- * die - the DIE we're interested in
- * name - the name of the attribute to lookup
- * valp - pointer to where the value of the attribute is placed
- * req - if the value is required (0 / non-zero)
- *
- * If the attribute is not found, one of the following happens:
- * - program terminates (req is non-zero)
- * - function returns 0
- *
- * If the value is found, and in a form (class) we can handle, the function
- * returns 1.
- *
- * Currently, we can only handle attribute values that are stored as
- * constants (immediate value). If an attribute has a form we cannot
- * handle (for example VLAs may store the dimensions of the array
- * as a DWARF expression that can compute it at runtime by reading
- * values off the stack or other locations in memory), it is treated
- * the same as if the attribute does not exist.
- */
-static int
-die_signed(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Signed *valp,
- int req)
-{
- Dwarf_Attribute attr;
- Dwarf_Signed val;
-
- if ((attr = die_attr(dw, die, name, req)) == NULL)
- return (0); /* die_attr will terminate for us if necessary */
-
- if (dwarf_formsdata(attr, &val, &dw->dw_err) != DW_DLV_OK) {
- if (req == 0)
- return (0);
-
- terminate("die %llu: failed to get signed (form 0x%x)\n",
- die_off(dw, die), die_attr_form(dw, attr));
- }
-
- dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR);
-
- *valp = val;
- return (1);
-}
-
-static int
-die_unsigned(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Unsigned *valp,
- int req)
-{
- Dwarf_Attribute attr;
- Dwarf_Unsigned val;
-
- if ((attr = die_attr(dw, die, name, req)) == NULL)
- return (0); /* die_attr will terminate for us if necessary */
-
- if (dwarf_formudata(attr, &val, &dw->dw_err) != DW_DLV_OK) {
- if (req == 0)
- return (0);
-
- terminate("die %llu: failed to get unsigned (form 0x%x)\n",
- die_off(dw, die), die_attr_form(dw, attr));
- }
-
- dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR);
-
- *valp = val;
- return (1);
-}
-
-static int
-die_bool(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Bool *valp, int req)
-{
- Dwarf_Attribute attr;
- Dwarf_Bool val;
-
- if ((attr = die_attr(dw, die, name, req)) == NULL)
- return (0); /* die_attr will terminate for us if necessary */
-
- if (dwarf_formflag(attr, &val, &dw->dw_err) != DW_DLV_OK) {
- if (req == 0)
- return (0);
-
- terminate("die %llu: failed to get bool (form 0x%x)\n",
- die_off(dw, die), die_attr_form(dw, attr));
- }
-
- dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR);
-
- *valp = val;
- return (1);
-}
-
-static int
-die_string(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, char **strp, int req)
-{
- Dwarf_Attribute attr;
- char *str;
-
- if ((attr = die_attr(dw, die, name, req)) == NULL)
- return (0); /* die_attr will terminate for us if necessary */
-
- if (dwarf_formstring(attr, &str, &dw->dw_err) != DW_DLV_OK) {
- if (req == 0)
- return (0);
-
- terminate("die %llu: failed to get string (form 0x%x)\n",
- die_off(dw, die), die_attr_form(dw, attr));
- }
-
- *strp = xstrdup(str);
- dwarf_dealloc(dw->dw_dw, str, DW_DLA_STRING);
-
- return (1);
-}
-
-static Dwarf_Off
-die_attr_ref(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name)
-{
- Dwarf_Attribute attr;
- Dwarf_Off off;
-
- attr = die_attr(dw, die, name, DW_ATTR_REQ);
-
- if (dwarf_formref(attr, &off, &dw->dw_err) != DW_DLV_OK) {
- terminate("die %llu: failed to get ref (form 0x%x)\n",
- die_off(dw, die), die_attr_form(dw, attr));
- }
-
- dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR);
-
- return (off);
-}
-
-static char *
-die_name(dwarf_t *dw, Dwarf_Die die)
-{
- char *str = NULL;
-
- (void) die_string(dw, die, DW_AT_name, &str, 0);
-
- return (str);
-}
-
-static int
-die_isdecl(dwarf_t *dw, Dwarf_Die die)
-{
- Dwarf_Bool val;
-
- return (die_bool(dw, die, DW_AT_declaration, &val, 0) && val);
-}
-
-static int
-die_isglobal(dwarf_t *dw, Dwarf_Die die)
-{
- Dwarf_Signed vis;
- Dwarf_Bool ext;
-
- /*
- * Some compilers (gcc) use DW_AT_external to indicate function
- * visibility. Others (Sun) use DW_AT_visibility.
- */
- if (die_signed(dw, die, DW_AT_visibility, &vis, 0))
- return (vis == DW_VIS_exported);
- else
- return (die_bool(dw, die, DW_AT_external, &ext, 0) && ext);
-}
-
-static tdesc_t *
-die_add(dwarf_t *dw, Dwarf_Off off)
-{
- tdesc_t *tdp = xcalloc(sizeof (tdesc_t));
-
- tdp->t_id = off;
-
- tdesc_add(dw, tdp);
-
- return (tdp);
-}
-
-static tdesc_t *
-die_lookup_pass1(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name)
-{
- Dwarf_Off ref = die_attr_ref(dw, die, name);
- tdesc_t *tdp;
-
- if ((tdp = tdesc_lookup(dw, ref)) != NULL)
- return (tdp);
-
- return (die_add(dw, ref));
-}
-
-static int
-die_mem_offset(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name,
- Dwarf_Unsigned *valp, int req)
-{
- Dwarf_Attribute attr;
- Dwarf_Locdesc *loc;
- Dwarf_Signed locnum;
-
- if ((attr = die_attr(dw, die, name, req)) == NULL)
- return (0); /* die_attr will terminate for us if necessary */
-
- if (dwarf_loclist(attr, &loc, &locnum, &dw->dw_err) != DW_DLV_OK) {
- terminate("die %llu: failed to get mem offset location list\n",
- die_off(dw, die));
- }
-
- dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR);
-
- if (locnum != 1 || loc->ld_s->lr_atom != DW_OP_plus_uconst) {
- terminate("die %llu: cannot parse member offset\n",
- die_off(dw, die));
- }
-
- *valp = loc->ld_s->lr_number;
-
- dwarf_dealloc(dw->dw_dw, loc->ld_s, DW_DLA_LOC_BLOCK);
- dwarf_dealloc(dw->dw_dw, loc, DW_DLA_LOCDESC);
-
- return (1);
-}
-
-static tdesc_t *
-tdesc_intr_common(dwarf_t *dw, int tid, const char *name, size_t sz)
-{
- tdesc_t *tdp;
- intr_t *intr;
-
- intr = xcalloc(sizeof (intr_t));
- intr->intr_type = INTR_INT;
- intr->intr_signed = 1;
- intr->intr_nbits = sz * NBBY;
-
- tdp = xcalloc(sizeof (tdesc_t));
- tdp->t_name = xstrdup(name);
- tdp->t_size = sz;
- tdp->t_id = tid;
- tdp->t_type = INTRINSIC;
- tdp->t_intr = intr;
- tdp->t_flags = TDESC_F_RESOLVED;
-
- tdesc_add(dw, tdp);
-
- return (tdp);
-}
-
-/*
- * Manufacture a void type. Used for gcc-emitted stabs, where the lack of a
- * type reference implies a reference to a void type. A void *, for example
- * will be represented by a pointer die without a DW_AT_type. CTF requires
- * that pointer nodes point to something, so we'll create a void for use as
- * the target. Note that the DWARF data may already create a void type. Ours
- * would then be a duplicate, but it'll be removed in the self-uniquification
- * merge performed at the completion of DWARF->tdesc conversion.
- */
-static tdesc_t *
-tdesc_intr_void(dwarf_t *dw)
-{
- if (dw->dw_void == NULL)
- dw->dw_void = tdesc_intr_common(dw, TID_VOID, "void", 0);
-
- return (dw->dw_void);
-}
-
-static tdesc_t *
-tdesc_intr_long(dwarf_t *dw)
-{
- if (dw->dw_long == NULL) {
- dw->dw_long = tdesc_intr_common(dw, TID_LONG, "long",
- dw->dw_ptrsz);
- }
-
- return (dw->dw_long);
-}
-
-/*
- * Used for creating bitfield types. We create a copy of an existing intrinsic,
- * adjusting the size of the copy to match what the caller requested. The
- * caller can then use the copy as the type for a bitfield structure member.
- */
-static tdesc_t *
-tdesc_intr_clone(dwarf_t *dw, tdesc_t *old, size_t bitsz)
-{
- tdesc_t *new = xcalloc(sizeof (tdesc_t));
-
- if (!(old->t_flags & TDESC_F_RESOLVED)) {
- terminate("tdp %u: attempt to make a bit field from an "
- "unresolved type\n", old->t_id);
- }
-
- new->t_name = xstrdup(old->t_name);
- new->t_size = old->t_size;
- new->t_id = mfgtid_next(dw);
- new->t_type = INTRINSIC;
- new->t_flags = TDESC_F_RESOLVED;
-
- new->t_intr = xcalloc(sizeof (intr_t));
- bcopy(old->t_intr, new->t_intr, sizeof (intr_t));
- new->t_intr->intr_nbits = bitsz;
-
- tdesc_add(dw, new);
-
- return (new);
-}
-
-static void
-tdesc_array_create(dwarf_t *dw, Dwarf_Die dim, tdesc_t *arrtdp,
- tdesc_t *dimtdp)
-{
- Dwarf_Unsigned uval;
- Dwarf_Signed sval;
- tdesc_t *ctdp;
- Dwarf_Die dim2;
- ardef_t *ar;
-
- if ((dim2 = die_sibling(dw, dim)) == NULL) {
- ctdp = arrtdp;
- } else if (die_tag(dw, dim2) == DW_TAG_subrange_type) {
- ctdp = xcalloc(sizeof (tdesc_t));
- ctdp->t_id = mfgtid_next(dw);
- debug(3, "die %llu: creating new type %u for sub-dimension\n",
- die_off(dw, dim2), ctdp->t_id);
- tdesc_array_create(dw, dim2, arrtdp, ctdp);
- } else {
- terminate("die %llu: unexpected non-subrange node in array\n",
- die_off(dw, dim2));
- }
-
- dimtdp->t_type = ARRAY;
- dimtdp->t_ardef = ar = xcalloc(sizeof (ardef_t));
-
- /*
- * Array bounds can be signed or unsigned, but there are several kinds
- * of signless forms (data1, data2, etc) that take their sign from the
- * routine that is trying to interpret them. That is, data1 can be
- * either signed or unsigned, depending on whether you use the signed or
- * unsigned accessor function. GCC will use the signless forms to store
- * unsigned values which have their high bit set, so we need to try to
- * read them first as unsigned to get positive values. We could also
- * try signed first, falling back to unsigned if we got a negative
- * value.
- */
- if (die_unsigned(dw, dim, DW_AT_upper_bound, &uval, 0))
- ar->ad_nelems = uval + 1;
- else if (die_signed(dw, dim, DW_AT_upper_bound, &sval, 0))
- ar->ad_nelems = sval + 1;
- else
- ar->ad_nelems = 0;
-
- /*
- * Different compilers use different index types. Force the type to be
- * a common, known value (long).
- */
- ar->ad_idxtype = tdesc_intr_long(dw);
- ar->ad_contents = ctdp;
-
- if (ar->ad_contents->t_size != 0) {
- dimtdp->t_size = ar->ad_contents->t_size * ar->ad_nelems;
- dimtdp->t_flags |= TDESC_F_RESOLVED;
- }
-}
-
-/*
- * Create a tdesc from an array node. Some arrays will come with byte size
- * attributes, and thus can be resolved immediately. Others don't, and will
- * need to wait until the second pass for resolution.
- */
-static void
-die_array_create(dwarf_t *dw, Dwarf_Die arr, Dwarf_Off off, tdesc_t *tdp)
-{
- tdesc_t *arrtdp = die_lookup_pass1(dw, arr, DW_AT_type);
- Dwarf_Unsigned uval;
- Dwarf_Die dim;
-
- debug(3, "die %llu: creating array\n", off);
-
- if ((dim = die_child(dw, arr)) == NULL ||
- die_tag(dw, dim) != DW_TAG_subrange_type)
- terminate("die %llu: failed to retrieve array bounds\n", off);
-
- tdesc_array_create(dw, dim, arrtdp, tdp);
-
- if (die_unsigned(dw, arr, DW_AT_byte_size, &uval, 0)) {
- tdesc_t *dimtdp;
- int flags;
-
- tdp->t_size = uval;
-
- /*
- * Ensure that sub-dimensions have sizes too before marking
- * as resolved.
- */
- flags = TDESC_F_RESOLVED;
- for (dimtdp = tdp->t_ardef->ad_contents;
- dimtdp->t_type == ARRAY;
- dimtdp = dimtdp->t_ardef->ad_contents) {
- if (!(dimtdp->t_flags & TDESC_F_RESOLVED)) {
- flags = 0;
- break;
- }
- }
-
- tdp->t_flags |= flags;
- }
-
- debug(3, "die %llu: array nelems %u size %u\n", off,
- tdp->t_ardef->ad_nelems, tdp->t_size);
-}
-
-/*ARGSUSED1*/
-static int
-die_array_resolve(tdesc_t *tdp, tdesc_t **tdpp, void *private)
-{
- dwarf_t *dw = private;
- size_t sz;
-
- if (tdp->t_flags & TDESC_F_RESOLVED)
- return (1);
-
- debug(3, "trying to resolve array %d (cont %d)\n", tdp->t_id,
- tdp->t_ardef->ad_contents->t_id);
-
- if ((sz = tdesc_size(tdp->t_ardef->ad_contents)) == 0) {
- debug(3, "unable to resolve array %s (%d) contents %d\n",
- tdesc_name(tdp), tdp->t_id,
- tdp->t_ardef->ad_contents->t_id);
-
- dw->dw_nunres++;
- return (1);
- }
-
- tdp->t_size = sz * tdp->t_ardef->ad_nelems;
- tdp->t_flags |= TDESC_F_RESOLVED;
-
- debug(3, "resolved array %d: %u bytes\n", tdp->t_id, tdp->t_size);
-
- return (1);
-}
-
-/*ARGSUSED1*/
-static int
-die_array_failed(tdesc_t *tdp, tdesc_t **tdpp, void *private)
-{
- tdesc_t *cont = tdp->t_ardef->ad_contents;
-
- if (tdp->t_flags & TDESC_F_RESOLVED)
- return (1);
-
- fprintf(stderr, "Array %d: failed to size contents type %s (%d)\n",
- tdp->t_id, tdesc_name(cont), cont->t_id);
-
- return (1);
-}
-
-/*
- * Most enums (those with members) will be resolved during this first pass.
- * Others - those without members (see the file comment) - won't be, and will
- * need to wait until the second pass when they can be matched with their full
- * definitions.
- */
-static void
-die_enum_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp)
-{
- Dwarf_Die mem;
- Dwarf_Unsigned uval;
- Dwarf_Signed sval;
-
- debug(3, "die %llu: creating enum\n", off);
-
- tdp->t_type = ENUM;
-
- (void) die_unsigned(dw, die, DW_AT_byte_size, &uval, DW_ATTR_REQ);
- tdp->t_size = uval;
-
- if ((mem = die_child(dw, die)) != NULL) {
- elist_t **elastp = &tdp->t_emem;
-
- do {
- elist_t *el;
-
- if (die_tag(dw, mem) != DW_TAG_enumerator) {
- /* Nested type declaration */
- die_create_one(dw, mem);
- continue;
- }
-
- el = xcalloc(sizeof (elist_t));
- el->el_name = die_name(dw, mem);
-
- /*
- * We have to be careful here: newer GCCs generate DWARF
- * where an unsigned value will happily pass
- * die_signed(). Since negative values will fail
- * die_unsigned(), we try that first to make sure we get
- * the right value.
- */
- if (die_unsigned(dw, mem, DW_AT_const_value,
- &uval, 0)) {
- el->el_number = uval;
- } else if (die_signed(dw, mem, DW_AT_const_value,
- &sval, 0)) {
- el->el_number = sval;
- } else {
- terminate("die %llu: enum %llu: member without "
- "value\n", off, die_off(dw, mem));
- }
-
- debug(3, "die %llu: enum %llu: created %s = %d\n", off,
- die_off(dw, mem), el->el_name, el->el_number);
-
- *elastp = el;
- elastp = &el->el_next;
-
- } while ((mem = die_sibling(dw, mem)) != NULL);
-
- hash_add(dw->dw_enumhash, tdp);
-
- tdp->t_flags |= TDESC_F_RESOLVED;
-
- if (tdp->t_name != NULL) {
- iidesc_t *ii = xcalloc(sizeof (iidesc_t));
- ii->ii_type = II_SOU;
- ii->ii_name = xstrdup(tdp->t_name);
- ii->ii_dtype = tdp;
-
- iidesc_add(dw->dw_td->td_iihash, ii);
- }
- }
-}
-
-static int
-die_enum_match(void *arg1, void *arg2)
-{
- tdesc_t *tdp = arg1, **fullp = arg2;
-
- if (tdp->t_emem != NULL) {
- *fullp = tdp;
- return (-1); /* stop the iteration */
- }
-
- return (0);
-}
-
-/*ARGSUSED1*/
-static int
-die_enum_resolve(tdesc_t *tdp, tdesc_t **tdpp, void *private)
-{
- dwarf_t *dw = private;
- tdesc_t *full = NULL;
-
- if (tdp->t_flags & TDESC_F_RESOLVED)
- return (1);
-
- (void) hash_find_iter(dw->dw_enumhash, tdp, die_enum_match, &full);
-
- /*
- * The answer to this one won't change from iteration to iteration,
- * so don't even try.
- */
- if (full == NULL) {
- terminate("tdp %u: enum %s has no members\n", tdp->t_id,
- tdesc_name(tdp));
- }
-
- debug(3, "tdp %u: enum %s redirected to %u\n", tdp->t_id,
- tdesc_name(tdp), full->t_id);
-
- tdp->t_flags |= TDESC_F_RESOLVED;
-
- return (1);
-}
-
-static int
-die_fwd_map(void *arg1, void *arg2)
-{
- tdesc_t *fwd = arg1, *sou = arg2;
-
- debug(3, "tdp %u: mapped forward %s to sou %u\n", fwd->t_id,
- tdesc_name(fwd), sou->t_id);
- fwd->t_tdesc = sou;
-
- return (0);
-}
-
-/*
- * Structures and unions will never be resolved during the first pass, as we
- * won't be able to fully determine the member sizes. The second pass, which
- * have access to sizing information, will be able to complete the resolution.
- */
-static void
-die_sou_create(dwarf_t *dw, Dwarf_Die str, Dwarf_Off off, tdesc_t *tdp,
- int type, const char *typename)
-{
- Dwarf_Unsigned sz, bitsz, bitoff;
- Dwarf_Die mem;
- mlist_t *ml, **mlastp;
- iidesc_t *ii;
-
- tdp->t_type = (die_isdecl(dw, str) ? FORWARD : type);
-
- debug(3, "die %llu: creating %s %s\n", off,
- (tdp->t_type == FORWARD ? "forward decl" : typename),
- tdesc_name(tdp));
-
- if (tdp->t_type == FORWARD) {
- hash_add(dw->dw_fwdhash, tdp);
- return;
- }
-
- (void) hash_find_iter(dw->dw_fwdhash, tdp, die_fwd_map, tdp);
-
- (void) die_unsigned(dw, str, DW_AT_byte_size, &sz, DW_ATTR_REQ);
- tdp->t_size = sz;
-
- /*
- * GCC allows empty SOUs as an extension.
- */
- if ((mem = die_child(dw, str)) == NULL)
- goto out;
-
- mlastp = &tdp->t_members;
-
- do {
- Dwarf_Off memoff = die_off(dw, mem);
- Dwarf_Half tag = die_tag(dw, mem);
- Dwarf_Unsigned mloff;
-
- if (tag != DW_TAG_member) {
- /* Nested type declaration */
- die_create_one(dw, mem);
- continue;
- }
-
- debug(3, "die %llu: mem %llu: creating member\n", off, memoff);
-
- ml = xcalloc(sizeof (mlist_t));
-
- /*
- * This could be a GCC anon struct/union member, so we'll allow
- * an empty name, even though nothing can really handle them
- * properly. Note that some versions of GCC miss out debug
- * info for anon structs, though recent versions are fixed (gcc
- * bug 11816).
- */
- if ((ml->ml_name = die_name(dw, mem)) == NULL)
- ml->ml_name = "";
-
- ml->ml_type = die_lookup_pass1(dw, mem, DW_AT_type);
-
- if (die_mem_offset(dw, mem, DW_AT_data_member_location,
- &mloff, 0)) {
- debug(3, "die %llu: got mloff %llx\n", off,
- (u_longlong_t)mloff);
- ml->ml_offset = mloff * 8;
- }
-
- if (die_unsigned(dw, mem, DW_AT_bit_size, &bitsz, 0))
- ml->ml_size = bitsz;
- else
- ml->ml_size = tdesc_bitsize(ml->ml_type);
-
- if (die_unsigned(dw, mem, DW_AT_bit_offset, &bitoff, 0)) {
-#ifdef _BIG_ENDIAN
- ml->ml_offset += bitoff;
-#else
- ml->ml_offset += tdesc_bitsize(ml->ml_type) - bitoff -
- ml->ml_size;
-#endif
- }
-
- debug(3, "die %llu: mem %llu: created \"%s\" (off %u sz %u)\n",
- off, memoff, ml->ml_name, ml->ml_offset, ml->ml_size);
-
- *mlastp = ml;
- mlastp = &ml->ml_next;
- } while ((mem = die_sibling(dw, mem)) != NULL);
-
- /*
- * GCC will attempt to eliminate unused types, thus decreasing the
- * size of the emitted dwarf. That is, if you declare a foo_t in your
- * header, include said header in your source file, and neglect to
- * actually use (directly or indirectly) the foo_t in the source file,
- * the foo_t won't make it into the emitted DWARF. So, at least, goes
- * the theory.
- *
- * Occasionally, it'll emit the DW_TAG_structure_type for the foo_t,
- * and then neglect to emit the members. Strangely, the loner struct
- * tag will always be followed by a proper nested declaration of
- * something else. This is clearly a bug, but we're not going to have
- * time to get it fixed before this goo goes back, so we'll have to work
- * around it. If we see a no-membered struct with a nested declaration
- * (i.e. die_child of the struct tag won't be null), we'll ignore it.
- * Being paranoid, we won't simply remove it from the hash. Instead,
- * we'll decline to create an iidesc for it, thus ensuring that this
- * type won't make it into the output file. To be safe, we'll also
- * change the name.
- */
- if (tdp->t_members == NULL) {
- const char *old = tdesc_name(tdp);
- size_t newsz = 7 + strlen(old) + 1;
- char *new = xmalloc(newsz);
- (void) snprintf(new, newsz, "orphan %s", old);
-
- debug(3, "die %llu: worked around %s %s\n", off, typename, old);
-
- if (tdp->t_name != NULL)
- free(tdp->t_name);
- tdp->t_name = new;
- return;
- }
-
-out:
- if (tdp->t_name != NULL) {
- ii = xcalloc(sizeof (iidesc_t));
- ii->ii_type = II_SOU;
- ii->ii_name = xstrdup(tdp->t_name);
- ii->ii_dtype = tdp;
-
- iidesc_add(dw->dw_td->td_iihash, ii);
- }
-}
-
-static void
-die_struct_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp)
-{
- die_sou_create(dw, die, off, tdp, STRUCT, "struct");
-}
-
-static void
-die_union_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp)
-{
- die_sou_create(dw, die, off, tdp, UNION, "union");
-}
-
-/*ARGSUSED1*/
-static int
-die_sou_resolve(tdesc_t *tdp, tdesc_t **tdpp, void *private)
-{
- dwarf_t *dw = private;
- mlist_t *ml;
- tdesc_t *mt;
-
- if (tdp->t_flags & TDESC_F_RESOLVED)
- return (1);
-
- debug(3, "resolving sou %s\n", tdesc_name(tdp));
-
- for (ml = tdp->t_members; ml != NULL; ml = ml->ml_next) {
- if (ml->ml_size == 0) {
- mt = tdesc_basetype(ml->ml_type);
-
- if ((ml->ml_size = tdesc_bitsize(mt)) != 0)
- continue;
-
- /*
- * For empty members, or GCC/C99 flexible array
- * members, a size of 0 is correct.
- */
- if (mt->t_members == NULL)
- continue;
- if (mt->t_type == ARRAY && mt->t_ardef->ad_nelems == 0)
- continue;
-
- dw->dw_nunres++;
- return (1);
- }
-
- if ((mt = tdesc_basetype(ml->ml_type)) == NULL) {
- dw->dw_nunres++;
- return (1);
- }
-
- if (ml->ml_size != 0 && mt->t_type == INTRINSIC &&
- mt->t_intr->intr_nbits != ml->ml_size) {
- /*
- * This member is a bitfield, and needs to reference
- * an intrinsic type with the same width. If the
- * currently-referenced type isn't of the same width,
- * we'll copy it, adjusting the width of the copy to
- * the size we'd like.
- */
- debug(3, "tdp %u: creating bitfield for %d bits\n",
- tdp->t_id, ml->ml_size);
-
- ml->ml_type = tdesc_intr_clone(dw, mt, ml->ml_size);
- }
- }
-
- tdp->t_flags |= TDESC_F_RESOLVED;
-
- return (1);
-}
-
-/*ARGSUSED1*/
-static int
-die_sou_failed(tdesc_t *tdp, tdesc_t **tdpp, void *private)
-{
- const char *typename = (tdp->t_type == STRUCT ? "struct" : "union");
- mlist_t *ml;
-
- if (tdp->t_flags & TDESC_F_RESOLVED)
- return (1);
-
- for (ml = tdp->t_members; ml != NULL; ml = ml->ml_next) {
- if (ml->ml_size == 0) {
- fprintf(stderr, "%s %d: failed to size member \"%s\" "
- "of type %s (%d)\n", typename, tdp->t_id,
- ml->ml_name, tdesc_name(ml->ml_type),
- ml->ml_type->t_id);
- }
- }
-
- return (1);
-}
-
-static void
-die_funcptr_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp)
-{
- Dwarf_Attribute attr;
- Dwarf_Half tag;
- Dwarf_Die arg;
- fndef_t *fn;
- int i;
-
- debug(3, "die %llu: creating function pointer\n", off);
-
- /*
- * We'll begin by processing any type definition nodes that may be
- * lurking underneath this one.
- */
- for (arg = die_child(dw, die); arg != NULL;
- arg = die_sibling(dw, arg)) {
- if ((tag = die_tag(dw, arg)) != DW_TAG_formal_parameter &&
- tag != DW_TAG_unspecified_parameters) {
- /* Nested type declaration */
- die_create_one(dw, arg);
- }
- }
-
- if (die_isdecl(dw, die)) {
- /*
- * This is a prototype. We don't add prototypes to the
- * tree, so we're going to drop the tdesc. Unfortunately,
- * it has already been added to the tree. Nobody will reference
- * it, though, and it will be leaked.
- */
- return;
- }
-
- fn = xcalloc(sizeof (fndef_t));
-
- tdp->t_type = FUNCTION;
-
- if ((attr = die_attr(dw, die, DW_AT_type, 0)) != NULL) {
- dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR);
- fn->fn_ret = die_lookup_pass1(dw, die, DW_AT_type);
- } else {
- fn->fn_ret = tdesc_intr_void(dw);
- }
-
- /*
- * Count the arguments to the function, then read them in.
- */
- for (fn->fn_nargs = 0, arg = die_child(dw, die); arg != NULL;
- arg = die_sibling(dw, arg)) {
- if ((tag = die_tag(dw, arg)) == DW_TAG_formal_parameter)
- fn->fn_nargs++;
- else if (tag == DW_TAG_unspecified_parameters &&
- fn->fn_nargs > 0)
- fn->fn_vargs = 1;
- }
-
- if (fn->fn_nargs != 0) {
- debug(3, "die %llu: adding %d argument%s\n", off, fn->fn_nargs,
- (fn->fn_nargs > 1 ? "s" : ""));
-
- fn->fn_args = xcalloc(sizeof (tdesc_t *) * fn->fn_nargs);
- for (i = 0, arg = die_child(dw, die);
- arg != NULL && i < fn->fn_nargs;
- arg = die_sibling(dw, arg)) {
- if (die_tag(dw, arg) != DW_TAG_formal_parameter)
- continue;
-
- fn->fn_args[i++] = die_lookup_pass1(dw, arg,
- DW_AT_type);
- }
- }
-
- tdp->t_fndef = fn;
- tdp->t_flags |= TDESC_F_RESOLVED;
-}
-
-/*
- * GCC and DevPro use different names for the base types. While the terms are
- * the same, they are arranged in a different order. Some terms, such as int,
- * are implied in one, and explicitly named in the other. Given a base type
- * as input, this routine will return a common name, along with an intr_t
- * that reflects said name.
- */
-static intr_t *
-die_base_name_parse(const char *name, char **newp)
-{
- char buf[100];
- char *base, *c;
- int nlong = 0, nshort = 0, nchar = 0, nint = 0;
- int sign = 1;
- char fmt = '\0';
- intr_t *intr;
-
- if (strlen(name) > sizeof (buf) - 1)
- terminate("base type name \"%s\" is too long\n", name);
-
- strncpy(buf, name, sizeof (buf));
-
- for (c = strtok(buf, " "); c != NULL; c = strtok(NULL, " ")) {
- if (strcmp(c, "signed") == 0)
- sign = 1;
- else if (strcmp(c, "unsigned") == 0)
- sign = 0;
- else if (strcmp(c, "long") == 0)
- nlong++;
- else if (strcmp(c, "char") == 0) {
- nchar++;
- fmt = 'c';
- } else if (strcmp(c, "short") == 0)
- nshort++;
- else if (strcmp(c, "int") == 0)
- nint++;
- else {
- /*
- * If we don't recognize any of the tokens, we'll tell
- * the caller to fall back to the dwarf-provided
- * encoding information.
- */
- return (NULL);
- }
- }
-
- if (nchar > 1 || nshort > 1 || nint > 1 || nlong > 2)
- return (NULL);
-
- if (nchar > 0) {
- if (nlong > 0 || nshort > 0 || nint > 0)
- return (NULL);
-
- base = "char";
-
- } else if (nshort > 0) {
- if (nlong > 0)
- return (NULL);
-
- base = "short";
-
- } else if (nlong > 0) {
- base = "long";
-
- } else {
- base = "int";
- }
-
- intr = xcalloc(sizeof (intr_t));
- intr->intr_type = INTR_INT;
- intr->intr_signed = sign;
- intr->intr_iformat = fmt;
-
- snprintf(buf, sizeof (buf), "%s%s%s",
- (sign ? "" : "unsigned "),
- (nlong > 1 ? "long " : ""),
- base);
-
- *newp = xstrdup(buf);
- return (intr);
-}
-
-typedef struct fp_size_map {
- size_t fsm_typesz[2]; /* size of {32,64} type */
- uint_t fsm_enc[3]; /* CTF_FP_* for {bare,cplx,imagry} type */
-} fp_size_map_t;
-
-static const fp_size_map_t fp_encodings[] = {
- { { 4, 4 }, { CTF_FP_SINGLE, CTF_FP_CPLX, CTF_FP_IMAGRY } },
- { { 8, 8 }, { CTF_FP_DOUBLE, CTF_FP_DCPLX, CTF_FP_DIMAGRY } },
-#ifdef __sparc
- { { 16, 16 }, { CTF_FP_LDOUBLE, CTF_FP_LDCPLX, CTF_FP_LDIMAGRY } },
-#else
- { { 12, 16 }, { CTF_FP_LDOUBLE, CTF_FP_LDCPLX, CTF_FP_LDIMAGRY } },
-#endif
- { { 0, 0 } }
-};
-
-static uint_t
-die_base_type2enc(dwarf_t *dw, Dwarf_Off off, Dwarf_Signed enc, size_t sz)
-{
- const fp_size_map_t *map = fp_encodings;
- uint_t szidx = dw->dw_ptrsz == sizeof (uint64_t);
- uint_t mult = 1, col = 0;
-
- if (enc == DW_ATE_complex_float) {
- mult = 2;
- col = 1;
- } else if (enc == DW_ATE_imaginary_float ||
- enc == DW_ATE_SUN_imaginary_float)
- col = 2;
-
- while (map->fsm_typesz[szidx] != 0) {
- if (map->fsm_typesz[szidx] * mult == sz)
- return (map->fsm_enc[col]);
- map++;
- }
-
- terminate("die %llu: unrecognized real type size %u\n", off, sz);
- /*NOTREACHED*/
- return (0);
-}
-
-static intr_t *
-die_base_from_dwarf(dwarf_t *dw, Dwarf_Die base, Dwarf_Off off, size_t sz)
-{
- intr_t *intr = xcalloc(sizeof (intr_t));
- Dwarf_Signed enc;
-
- (void) die_signed(dw, base, DW_AT_encoding, &enc, DW_ATTR_REQ);
-
- switch (enc) {
- case DW_ATE_unsigned:
- case DW_ATE_address:
- intr->intr_type = INTR_INT;
- break;
- case DW_ATE_unsigned_char:
- intr->intr_type = INTR_INT;
- intr->intr_iformat = 'c';
- break;
- case DW_ATE_signed:
- intr->intr_type = INTR_INT;
- intr->intr_signed = 1;
- break;
- case DW_ATE_signed_char:
- intr->intr_type = INTR_INT;
- intr->intr_signed = 1;
- intr->intr_iformat = 'c';
- break;
- case DW_ATE_boolean:
- intr->intr_type = INTR_INT;
- intr->intr_signed = 1;
- intr->intr_iformat = 'b';
- break;
- case DW_ATE_float:
- case DW_ATE_complex_float:
- case DW_ATE_imaginary_float:
- case DW_ATE_SUN_imaginary_float:
- case DW_ATE_SUN_interval_float:
- intr->intr_type = INTR_REAL;
- intr->intr_signed = 1;
- intr->intr_fformat = die_base_type2enc(dw, off, enc, sz);
- break;
- default:
- terminate("die %llu: unknown base type encoding 0x%llx\n",
- off, enc);
- }
-
- return (intr);
-}
-
-static void
-die_base_create(dwarf_t *dw, Dwarf_Die base, Dwarf_Off off, tdesc_t *tdp)
-{
- Dwarf_Unsigned sz;
- intr_t *intr;
- char *new;
-
- debug(3, "die %llu: creating base type\n", off);
-
- /*
- * The compilers have their own clever (internally inconsistent) ideas
- * as to what base types should look like. Some times gcc will, for
- * example, use DW_ATE_signed_char for char. Other times, however, it
- * will use DW_ATE_signed. Needless to say, this causes some problems
- * down the road, particularly with merging. We do, however, use the
- * DWARF idea of type sizes, as this allows us to avoid caring about
- * the data model.
- */
- (void) die_unsigned(dw, base, DW_AT_byte_size, &sz, DW_ATTR_REQ);
-
- if (tdp->t_name == NULL)
- terminate("die %llu: base type without name\n", off);
-
- /* XXX make a name parser for float too */
- if ((intr = die_base_name_parse(tdp->t_name, &new)) != NULL) {
- /* Found it. We'll use the parsed version */
- debug(3, "die %llu: name \"%s\" remapped to \"%s\"\n", off,
- tdesc_name(tdp), new);
-
- free(tdp->t_name);
- tdp->t_name = new;
- } else {
- /*
- * We didn't recognize the type, so we'll create an intr_t
- * based on the DWARF data.
- */
- debug(3, "die %llu: using dwarf data for base \"%s\"\n", off,
- tdesc_name(tdp));
-
- intr = die_base_from_dwarf(dw, base, off, sz);
- }
-
- intr->intr_nbits = sz * 8;
-
- tdp->t_type = INTRINSIC;
- tdp->t_intr = intr;
- tdp->t_size = sz;
-
- tdp->t_flags |= TDESC_F_RESOLVED;
-}
-
-static void
-die_through_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp,
- int type, const char *typename)
-{
- Dwarf_Attribute attr;
-
- debug(3, "die %llu: creating %s\n", off, typename);
-
- tdp->t_type = type;
-
- if ((attr = die_attr(dw, die, DW_AT_type, 0)) != NULL) {
- dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR);
- tdp->t_tdesc = die_lookup_pass1(dw, die, DW_AT_type);
- } else {
- tdp->t_tdesc = tdesc_intr_void(dw);
- }
-
- if (type == POINTER)
- tdp->t_size = dw->dw_ptrsz;
-
- tdp->t_flags |= TDESC_F_RESOLVED;
-
- if (type == TYPEDEF) {
- iidesc_t *ii = xcalloc(sizeof (iidesc_t));
- ii->ii_type = II_TYPE;
- ii->ii_name = xstrdup(tdp->t_name);
- ii->ii_dtype = tdp;
-
- iidesc_add(dw->dw_td->td_iihash, ii);
- }
-}
-
-static void
-die_typedef_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp)
-{
- die_through_create(dw, die, off, tdp, TYPEDEF, "typedef");
-}
-
-static void
-die_const_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp)
-{
- die_through_create(dw, die, off, tdp, CONST, "const");
-}
-
-static void
-die_pointer_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp)
-{
- die_through_create(dw, die, off, tdp, POINTER, "pointer");
-}
-
-static void
-die_restrict_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp)
-{
- die_through_create(dw, die, off, tdp, RESTRICT, "restrict");
-}
-
-static void
-die_volatile_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp)
-{
- die_through_create(dw, die, off, tdp, VOLATILE, "volatile");
-}
-
-/*ARGSUSED3*/
-static void
-die_function_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp)
-{
- Dwarf_Die arg;
- Dwarf_Half tag;
- iidesc_t *ii;
- char *name;
-
- debug(3, "die %llu: creating function definition\n", off);
-
- /*
- * We'll begin by processing any type definition nodes that may be
- * lurking underneath this one.
- */
- for (arg = die_child(dw, die); arg != NULL;
- arg = die_sibling(dw, arg)) {
- if ((tag = die_tag(dw, arg)) != DW_TAG_formal_parameter &&
- tag != DW_TAG_variable) {
- /* Nested type declaration */
- die_create_one(dw, arg);
- }
- }
-
- if (die_isdecl(dw, die) || (name = die_name(dw, die)) == NULL) {
- /*
- * We process neither prototypes nor subprograms without
- * names.
- */
- return;
- }
-
- ii = xcalloc(sizeof (iidesc_t));
- ii->ii_type = die_isglobal(dw, die) ? II_GFUN : II_SFUN;
- ii->ii_name = name;
- if (ii->ii_type == II_SFUN)
- ii->ii_owner = xstrdup(dw->dw_cuname);
-
- debug(3, "die %llu: function %s is %s\n", off, ii->ii_name,
- (ii->ii_type == II_GFUN ? "global" : "static"));
-
- if (die_attr(dw, die, DW_AT_type, 0) != NULL)
- ii->ii_dtype = die_lookup_pass1(dw, die, DW_AT_type);
- else
- ii->ii_dtype = tdesc_intr_void(dw);
-
- for (arg = die_child(dw, die); arg != NULL;
- arg = die_sibling(dw, arg)) {
- char *name;
-
- debug(3, "die %llu: looking at sub member at %llu\n",
- off, die_off(dw, die));
-
- if (die_tag(dw, arg) != DW_TAG_formal_parameter)
- continue;
-
- if ((name = die_name(dw, arg)) == NULL) {
- terminate("die %llu: func arg %d has no name\n",
- off, ii->ii_nargs + 1);
- }
-
- if (strcmp(name, "...") == 0) {
- free(name);
- ii->ii_vargs = 1;
- continue;
- }
-
- ii->ii_nargs++;
- }
-
- if (ii->ii_nargs > 0) {
- int i;
-
- debug(3, "die %llu: function has %d argument%s\n", off,
- ii->ii_nargs, (ii->ii_nargs == 1 ? "" : "s"));
-
- ii->ii_args = xcalloc(sizeof (tdesc_t) * ii->ii_nargs);
-
- for (arg = die_child(dw, die), i = 0;
- arg != NULL && i < ii->ii_nargs;
- arg = die_sibling(dw, arg)) {
- if (die_tag(dw, arg) != DW_TAG_formal_parameter)
- continue;
-
- ii->ii_args[i++] = die_lookup_pass1(dw, arg,
- DW_AT_type);
- }
- }
-
- iidesc_add(dw->dw_td->td_iihash, ii);
-}
-
-/*ARGSUSED3*/
-static void
-die_variable_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp)
-{
- iidesc_t *ii;
- char *name;
-
- debug(3, "die %llu: creating object definition\n", off);
-
- /* Skip "Non-Defining Declarations" */
- if (die_isdecl(dw, die))
- return;
-
- /*
- * If we find a DIE of "Declarations Completing Non-Defining
- * Declarations", we will use the referenced type's DIE. This isn't
- * quite correct, e.g. DW_AT_decl_line will be the forward declaration
- * not this site. It's sufficient for what we need, however: in
- * particular, we should find DW_AT_external as needed there.
- */
- if (die_attr(dw, die, DW_AT_specification, 0) != NULL) {
- Dwarf_Die sdie;
- Dwarf_Off soff;
-
- soff = die_attr_ref(dw, die, DW_AT_specification);
-
- if (dwarf_offdie(dw->dw_dw, soff,
- &sdie, &dw->dw_err) != DW_DLV_OK) {
- terminate("dwarf_offdie(%llu) failed: %s\n",
- soff, dwarf_errmsg(dw->dw_err));
- }
-
- die = sdie;
- }
-
- if ((name = die_name(dw, die)) == NULL)
- return;
-
- ii = xcalloc(sizeof (iidesc_t));
- ii->ii_type = die_isglobal(dw, die) ? II_GVAR : II_SVAR;
- ii->ii_name = name;
- ii->ii_dtype = die_lookup_pass1(dw, die, DW_AT_type);
- if (ii->ii_type == II_SVAR)
- ii->ii_owner = xstrdup(dw->dw_cuname);
-
- iidesc_add(dw->dw_td->td_iihash, ii);
-}
-
-/*ARGSUSED2*/
-static int
-die_fwd_resolve(tdesc_t *fwd, tdesc_t **fwdp, void *private)
-{
- if (fwd->t_flags & TDESC_F_RESOLVED)
- return (1);
-
- if (fwd->t_tdesc != NULL) {
- debug(3, "tdp %u: unforwarded %s\n", fwd->t_id,
- tdesc_name(fwd));
- *fwdp = fwd->t_tdesc;
- }
-
- fwd->t_flags |= TDESC_F_RESOLVED;
-
- return (1);
-}
-
-/*ARGSUSED*/
-static void
-die_lexblk_descend(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp)
-{
- Dwarf_Die child = die_child(dw, die);
-
- if (child != NULL)
- die_create(dw, child);
-}
-
-/*
- * Used to map the die to a routine which can parse it, using the tag to do the
- * mapping. While the processing of most tags entails the creation of a tdesc,
- * there are a few which don't - primarily those which result in the creation of
- * iidescs which refer to existing tdescs.
- */
-
-#define DW_F_NOTDP 0x1 /* Don't create a tdesc for the creator */
-
-typedef struct die_creator {
- Dwarf_Half dc_tag;
- uint16_t dc_flags;
- void (*dc_create)(dwarf_t *, Dwarf_Die, Dwarf_Off, tdesc_t *);
-} die_creator_t;
-
-static const die_creator_t die_creators[] = {
- { DW_TAG_array_type, 0, die_array_create },
- { DW_TAG_enumeration_type, 0, die_enum_create },
- { DW_TAG_lexical_block, DW_F_NOTDP, die_lexblk_descend },
- { DW_TAG_pointer_type, 0, die_pointer_create },
- { DW_TAG_structure_type, 0, die_struct_create },
- { DW_TAG_subroutine_type, 0, die_funcptr_create },
- { DW_TAG_typedef, 0, die_typedef_create },
- { DW_TAG_union_type, 0, die_union_create },
- { DW_TAG_base_type, 0, die_base_create },
- { DW_TAG_const_type, 0, die_const_create },
- { DW_TAG_subprogram, DW_F_NOTDP, die_function_create },
- { DW_TAG_variable, DW_F_NOTDP, die_variable_create },
- { DW_TAG_volatile_type, 0, die_volatile_create },
- { DW_TAG_restrict_type, 0, die_restrict_create },
- { 0, 0, NULL }
-};
-
-static const die_creator_t *
-die_tag2ctor(Dwarf_Half tag)
-{
- const die_creator_t *dc;
-
- for (dc = die_creators; dc->dc_create != NULL; dc++) {
- if (dc->dc_tag == tag)
- return (dc);
- }
-
- return (NULL);
-}
-
-static void
-die_create_one(dwarf_t *dw, Dwarf_Die die)
-{
- Dwarf_Off off = die_off(dw, die);
- const die_creator_t *dc;
- Dwarf_Half tag;
- tdesc_t *tdp;
-
- debug(3, "die %llu: create_one\n", off);
-
- if (off > dw->dw_maxoff) {
- terminate("illegal die offset %llu (max %llu)\n", off,
- dw->dw_maxoff);
- }
-
- tag = die_tag(dw, die);
-
- if ((dc = die_tag2ctor(tag)) == NULL) {
- debug(2, "die %llu: ignoring tag type %x\n", off, tag);
- return;
- }
-
- if ((tdp = tdesc_lookup(dw, off)) == NULL &&
- !(dc->dc_flags & DW_F_NOTDP)) {
- tdp = xcalloc(sizeof (tdesc_t));
- tdp->t_id = off;
- tdesc_add(dw, tdp);
- }
-
- if (tdp != NULL)
- tdp->t_name = die_name(dw, die);
-
- dc->dc_create(dw, die, off, tdp);
-}
-
-static void
-die_create(dwarf_t *dw, Dwarf_Die die)
-{
- do {
- die_create_one(dw, die);
- } while ((die = die_sibling(dw, die)) != NULL);
-}
-
-static tdtrav_cb_f die_resolvers[] = {
- NULL,
- NULL, /* intrinsic */
- NULL, /* pointer */
- die_array_resolve, /* array */
- NULL, /* function */
- die_sou_resolve, /* struct */
- die_sou_resolve, /* union */
- die_enum_resolve, /* enum */
- die_fwd_resolve, /* forward */
- NULL, /* typedef */
- NULL, /* typedef unres */
- NULL, /* volatile */
- NULL, /* const */
- NULL, /* restrict */
-};
-
-static tdtrav_cb_f die_fail_reporters[] = {
- NULL,
- NULL, /* intrinsic */
- NULL, /* pointer */
- die_array_failed, /* array */
- NULL, /* function */
- die_sou_failed, /* struct */
- die_sou_failed, /* union */
- NULL, /* enum */
- NULL, /* forward */
- NULL, /* typedef */
- NULL, /* typedef unres */
- NULL, /* volatile */
- NULL, /* const */
- NULL, /* restrict */
-};
-
-static void
-die_resolve(dwarf_t *dw)
-{
- int last = -1;
- int pass = 0;
-
- do {
- pass++;
- dw->dw_nunres = 0;
-
- (void) iitraverse_hash(dw->dw_td->td_iihash,
- &dw->dw_td->td_curvgen, NULL, NULL, die_resolvers, dw);
-
- debug(3, "resolve: pass %d, %u left\n", pass, dw->dw_nunres);
-
- if (dw->dw_nunres == last) {
- fprintf(stderr, "%s: failed to resolve the following "
- "types:\n", progname);
-
- (void) iitraverse_hash(dw->dw_td->td_iihash,
- &dw->dw_td->td_curvgen, NULL, NULL,
- die_fail_reporters, dw);
-
- terminate("failed to resolve types\n");
- }
-
- last = dw->dw_nunres;
-
- } while (dw->dw_nunres != 0);
-}
-
-/*
- * Any object containing a function or object symbol at any scope should also
- * contain DWARF data.
- */
-static boolean_t
-should_have_dwarf(Elf *elf)
-{
- Elf_Scn *scn = NULL;
- Elf_Data *data = NULL;
- GElf_Shdr shdr;
- GElf_Sym sym;
- uint32_t symdx = 0;
- size_t nsyms = 0;
- boolean_t found = B_FALSE;
-
- while ((scn = elf_nextscn(elf, scn)) != NULL) {
- gelf_getshdr(scn, &shdr);
-
- if (shdr.sh_type == SHT_SYMTAB) {
- found = B_TRUE;
- break;
- }
- }
-
- if (!found)
- terminate("cannot convert stripped objects\n");
-
- data = elf_getdata(scn, NULL);
- nsyms = shdr.sh_size / shdr.sh_entsize;
-
- for (symdx = 0; symdx < nsyms; symdx++) {
- gelf_getsym(data, symdx, &sym);
-
- if ((GELF_ST_TYPE(sym.st_info) == STT_FUNC) ||
- (GELF_ST_TYPE(sym.st_info) == STT_TLS) ||
- (GELF_ST_TYPE(sym.st_info) == STT_OBJECT)) {
- char *name;
-
- name = elf_strptr(elf, shdr.sh_link, sym.st_name);
-
- /* Studio emits these local symbols regardless */
- if ((strcmp(name, "Bbss.bss") != 0) &&
- (strcmp(name, "Ttbss.bss") != 0) &&
- (strcmp(name, "Ddata.data") != 0) &&
- (strcmp(name, "Ttdata.data") != 0) &&
- (strcmp(name, "Drodata.rodata") != 0))
- return (B_TRUE);
- }
- }
-
- return (B_FALSE);
-}
-
-/*ARGSUSED*/
-int
-dw_read(tdata_t *td, Elf *elf, const char *filename)
-{
- Dwarf_Unsigned abboff, hdrlen, nxthdr;
- Dwarf_Half vers, addrsz;
- Dwarf_Die cu, child;
- dwarf_t dw;
- char *prod = NULL;
- int rc;
-
- bzero(&dw, sizeof (dwarf_t));
- dw.dw_td = td;
- dw.dw_ptrsz = elf_ptrsz(elf);
- dw.dw_mfgtid_last = TID_MFGTID_BASE;
- dw.dw_tidhash = hash_new(TDESC_HASH_BUCKETS, tdesc_idhash, tdesc_idcmp);
- dw.dw_fwdhash = hash_new(TDESC_HASH_BUCKETS, tdesc_namehash,
- tdesc_namecmp);
- dw.dw_enumhash = hash_new(TDESC_HASH_BUCKETS, tdesc_namehash,
- tdesc_namecmp);
-
- if ((rc = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dw.dw_dw,
- &dw.dw_err)) == DW_DLV_NO_ENTRY) {
- if (should_have_dwarf(elf)) {
- errno = ENOENT;
- return (-1);
- } else {
- return (0);
- }
- } else if (rc != DW_DLV_OK) {
- if (dwarf_errno(dw.dw_err) == DW_DLE_DEBUG_INFO_NULL) {
- /*
- * There's no type data in the DWARF section, but
- * libdwarf is too clever to handle that properly.
- */
- return (0);
- }
-
- terminate("failed to initialize DWARF: %s\n",
- dwarf_errmsg(dw.dw_err));
- }
-
- if ((rc = dwarf_next_cu_header(dw.dw_dw, &hdrlen, &vers, &abboff,
- &addrsz, &nxthdr, &dw.dw_err)) != DW_DLV_OK)
- terminate("file does not contain valid DWARF data: %s\n",
- dwarf_errmsg(dw.dw_err));
-
- /*
- * Some compilers emit no DWARF for empty files, others emit an empty
- * compilation unit.
- */
- if ((cu = die_sibling(&dw, NULL)) == NULL ||
- ((child = die_child(&dw, cu)) == NULL) &&
- should_have_dwarf(elf)) {
- terminate("file does not contain dwarf type data "
- "(try compiling with -g)\n");
- } else if (child == NULL) {
- return (0);
- }
-
- dw.dw_maxoff = nxthdr - 1;
-
- if (dw.dw_maxoff > TID_FILEMAX)
- terminate("file contains too many types\n");
-
- debug(1, "DWARF version: %d\n", vers);
- if (vers != DWARF_VERSION) {
- terminate("file contains incompatible version %d DWARF code "
- "(version 2 required)\n", vers);
- }
-
- if (die_string(&dw, cu, DW_AT_producer, &prod, 0)) {
- debug(1, "DWARF emitter: %s\n", prod);
- free(prod);
- }
-
- if ((dw.dw_cuname = die_name(&dw, cu)) != NULL) {
- char *base = xstrdup(basename(dw.dw_cuname));
- free(dw.dw_cuname);
- dw.dw_cuname = base;
-
- debug(1, "CU name: %s\n", dw.dw_cuname);
- }
-
- die_create(&dw, child);
-
- if ((rc = dwarf_next_cu_header(dw.dw_dw, &hdrlen, &vers, &abboff,
- &addrsz, &nxthdr, &dw.dw_err)) != DW_DLV_NO_ENTRY)
- terminate("multiple compilation units not supported\n");
-
- (void) dwarf_finish(dw.dw_dw, &dw.dw_err);
-
- die_resolve(&dw);
-
- cvt_fixups(td, dw.dw_ptrsz);
-
- /* leak the dwarf_t */
-
- return (0);
-}
diff --git a/usr/src/tools/ctf/cvt/fifo.c b/usr/src/tools/ctf/cvt/fifo.c
deleted file mode 100644
index fb9a11fccf..0000000000
--- a/usr/src/tools/ctf/cvt/fifo.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * 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 2002 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Routines for manipulating a FIFO queue
- */
-
-#include <stdlib.h>
-
-#include "fifo.h"
-#include "memory.h"
-
-typedef struct fifonode {
- void *fn_data;
- struct fifonode *fn_next;
-} fifonode_t;
-
-struct fifo {
- fifonode_t *f_head;
- fifonode_t *f_tail;
-};
-
-fifo_t *
-fifo_new(void)
-{
- fifo_t *f;
-
- f = xcalloc(sizeof (fifo_t));
-
- return (f);
-}
-
-/* Add to the end of the fifo */
-void
-fifo_add(fifo_t *f, void *data)
-{
- fifonode_t *fn = xmalloc(sizeof (fifonode_t));
-
- fn->fn_data = data;
- fn->fn_next = NULL;
-
- if (f->f_tail == NULL)
- f->f_head = f->f_tail = fn;
- else {
- f->f_tail->fn_next = fn;
- f->f_tail = fn;
- }
-}
-
-/* Remove from the front of the fifo */
-void *
-fifo_remove(fifo_t *f)
-{
- fifonode_t *fn;
- void *data;
-
- if ((fn = f->f_head) == NULL)
- return (NULL);
-
- data = fn->fn_data;
- if ((f->f_head = fn->fn_next) == NULL)
- f->f_tail = NULL;
-
- free(fn);
-
- return (data);
-}
-
-/*ARGSUSED*/
-static void
-fifo_nullfree(void *arg)
-{
- /* this function intentionally left blank */
-}
-
-/* Free an entire fifo */
-void
-fifo_free(fifo_t *f, void (*freefn)(void *))
-{
- fifonode_t *fn = f->f_head;
- fifonode_t *tmp;
-
- if (freefn == NULL)
- freefn = fifo_nullfree;
-
- while (fn) {
- (*freefn)(fn->fn_data);
-
- tmp = fn;
- fn = fn->fn_next;
- free(tmp);
- }
-
- free(f);
-}
-
-int
-fifo_len(fifo_t *f)
-{
- fifonode_t *fn;
- int i;
-
- for (i = 0, fn = f->f_head; fn; fn = fn->fn_next, i++);
-
- return (i);
-}
-
-int
-fifo_empty(fifo_t *f)
-{
- return (f->f_head == NULL);
-}
-
-int
-fifo_iter(fifo_t *f, int (*iter)(void *data, void *arg), void *arg)
-{
- fifonode_t *fn;
- int rc;
- int ret = 0;
-
- for (fn = f->f_head; fn; fn = fn->fn_next) {
- if ((rc = iter(fn->fn_data, arg)) < 0)
- return (-1);
- ret += rc;
- }
-
- return (ret);
-}
diff --git a/usr/src/tools/ctf/cvt/fifo.h b/usr/src/tools/ctf/cvt/fifo.h
deleted file mode 100644
index e4b948abc4..0000000000
--- a/usr/src/tools/ctf/cvt/fifo.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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 2002 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _FIFO_H
-#define _FIFO_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Routines for manipulating a FIFO queue
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct fifo fifo_t;
-
-extern fifo_t *fifo_new(void);
-extern void fifo_add(fifo_t *, void *);
-extern void *fifo_remove(fifo_t *);
-extern void fifo_free(fifo_t *, void (*)(void *));
-extern int fifo_len(fifo_t *);
-extern int fifo_empty(fifo_t *);
-extern int fifo_iter(fifo_t *, int (*)(void *, void *), void *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _FIFO_H */
diff --git a/usr/src/tools/ctf/cvt/fixup_tdescs.c b/usr/src/tools/ctf/cvt/fixup_tdescs.c
deleted file mode 100644
index 8524693d02..0000000000
--- a/usr/src/tools/ctf/cvt/fixup_tdescs.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * 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.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Workarounds for stabs generation bugs in the compiler and general needed
- * fixups.
- */
-
-#include <stdio.h>
-#include <strings.h>
-
-#include "ctf_headers.h"
-#include "ctftools.h"
-#include "hash.h"
-#include "memory.h"
-
-/*
- * Due to 4432619, the 6.1 compiler will sometimes incorrectly generate pointer
- * stabs. Given a struct foo, and a corresponding typedef struct foo foo_t.
- * In some cases, when faced with a pointer to a foo_t, the compiler will
- * sometimes generate a stab that describes a pointer to a struct foo.
- * Regardless of correctness, this breaks merges, as it occurs inconsistently
- * by file. The following two routines know how to recognize and repair foo_t *
- * and foo_t ** bugs in a specific set of cases. There is no general way to
- * solve this problem without a fix to the compiler. In general, cases should
- * only be added to these routines to fix merging problems in genunix.
- */
-static void
-fix_ptrptr_to_struct(tdata_t *td)
-{
- char *strs[2] = { "as", "fdbuffer" };
- char *mems[2] = { "a_objectdir", "fd_shadow" };
- char *acts[2] = { "vnode", "page" };
- char *tgts[2] = { "vnode_t", "page_t" };
- tdesc_t *str;
- tdesc_t *act, *tgt;
- tdesc_t *p1, *p2;
- mlist_t *ml;
- int i;
-
- for (i = 0; i < sizeof (strs) / sizeof (strs[0]); i++) {
- if (!(str = lookupname(strs[i])) || str->t_type != STRUCT)
- continue;
-
- for (ml = str->t_members; ml; ml = ml->ml_next) {
- if (streq(ml->ml_name, mems[i]))
- break;
- }
- if (!ml)
- continue;
-
- if (ml->ml_type->t_type != POINTER || ml->ml_type->t_name ||
- ml->ml_type->t_tdesc->t_type != POINTER ||
- ml->ml_type->t_tdesc->t_name)
- continue;
-
- act = ml->ml_type->t_tdesc->t_tdesc;
- if (act->t_type != STRUCT || !streq(act->t_name, acts[i]))
- continue;
-
- if (!(tgt = lookupname(tgts[i])) || tgt->t_type != TYPEDEF)
- continue;
-
- /* We have an instance of the bug */
- p2 = xcalloc(sizeof (*p2));
- p2->t_type = POINTER;
- p2->t_id = td->td_nextid++;
- p2->t_tdesc = tgt;
-
- p1 = xcalloc(sizeof (*p1));
- p1->t_type = POINTER;
- p1->t_id = td->td_nextid++;
- p1->t_tdesc = p2;
-
- ml->ml_type = p1;
-
- debug(3, "Fixed %s->%s => ptrptr struct %s bug\n",
- strs[i], mems[i], acts[i]);
- }
-}
-
-static void
-fix_ptr_to_struct(tdata_t *td)
-{
- char *strs[2] = { "vmem", "id_space" };
- char *mems[2] = { NULL, "is_vmem" };
- tdesc_t *ptr = NULL;
- tdesc_t *str, *vmt;
- mlist_t *ml;
- int i;
-
- if ((vmt = lookupname("vmem_t")) == NULL || vmt->t_type != TYPEDEF)
- return;
-
- for (i = 0; i < sizeof (strs) / sizeof (strs[0]); i++) {
- if (!(str = lookupname(strs[i])) || str->t_type != STRUCT)
- continue;
-
- for (ml = str->t_members; ml; ml = ml->ml_next) {
- if (mems[i] && !streq(ml->ml_name, mems[i]))
- continue;
-
- if (ml->ml_type->t_type != POINTER ||
- ml->ml_type->t_name ||
- (ml->ml_type->t_tdesc->t_type != STRUCT &&
- ml->ml_type->t_tdesc->t_type != FORWARD) ||
- !streq(ml->ml_type->t_tdesc->t_name, "vmem"))
- continue;
-
- debug(3, "Fixed %s->%s => ptr struct vmem bug\n",
- strs[i], ml->ml_name);
-
- if (!ptr) {
- ptr = xcalloc(sizeof (*ptr));
- ptr->t_type = POINTER;
- ptr->t_id = td->td_nextid++;
- ptr->t_tdesc = vmt;
- }
-
- ml->ml_type = ptr;
- }
- }
-}
-
-/*
- * Fix stabs generation bugs. These routines must be run before the
- * post-conversion merge
- */
-void
-cvt_fixstabs(tdata_t *td)
-{
- fix_ptrptr_to_struct(td);
- fix_ptr_to_struct(td);
-}
-
-struct match {
- tdesc_t *m_ret;
- const char *m_name;
-};
-
-static int
-matching_iidesc(iidesc_t *iidesc, struct match *match)
-{
- if (!streq(iidesc->ii_name, match->m_name))
- return (0);
-
- if (iidesc->ii_type != II_TYPE && iidesc->ii_type != II_SOU)
- return (0);
-
- match->m_ret = iidesc->ii_dtype;
- return (-1);
-}
-
-static tdesc_t *
-lookup_tdesc(tdata_t *td, const char *name)
-{
- struct match match = { NULL, name };
- iter_iidescs_by_name(td, name, (int (*)())matching_iidesc, &match);
- return (match.m_ret);
-}
-
-/*
- * The cpu structure grows, with the addition of a machcpu member, if
- * _MACHDEP is defined. This means that, for example, the cpu structure
- * in unix is different from the cpu structure in genunix. As one might
- * expect, this causes merges to fail. Since everyone indirectly contains
- * a pointer to a CPU structure, the failed merges can cause massive amounts
- * of duplication. In the case of unix uniquifying against genunix, upwards
- * of 50% of the structures were unmerged due to this problem. We fix this
- * by adding a cpu_m member. If machcpu hasn't been defined in our module,
- * we make a forward node for it.
- */
-static void
-fix_small_cpu_struct(tdata_t *td, size_t ptrsize)
-{
- tdesc_t *cput, *cpu;
- tdesc_t *machcpu;
- mlist_t *ml, *lml;
- mlist_t *cpum;
- int foundcpucyc = 0;
-
- /*
- * We're going to take the circuitous route finding the cpu structure,
- * because we want to make sure that we find the right one. It would
- * be nice if we could verify the header name too. DWARF might not
- * have the cpu_t, so we let this pass.
- */
- if ((cput = lookup_tdesc(td, "cpu_t")) != NULL) {
- if (cput->t_type != TYPEDEF)
- return;
- cpu = cput->t_tdesc;
- } else {
- cpu = lookup_tdesc(td, "cpu");
- }
-
- if (cpu == NULL)
- return;
-
- if (!streq(cpu->t_name, "cpu") || cpu->t_type != STRUCT)
- return;
-
- for (ml = cpu->t_members, lml = NULL; ml;
- lml = ml, ml = ml->ml_next) {
- if (strcmp(ml->ml_name, "cpu_cyclic") == 0)
- foundcpucyc = 1;
- }
-
- if (foundcpucyc == 0 || lml == NULL ||
- strcmp(lml->ml_name, "cpu_m") == 0)
- return;
-
- /*
- * We need to derive the right offset for the fake cpu_m member. To do
- * that, we require a special unused member to be the last member
- * before the 'cpu_m', that we encode knowledge of here. ABI alignment
- * on all platforms is such that we only need to add a pointer-size
- * number of bits to get the right offset for cpu_m. This would most
- * likely break if gcc's -malign-double were ever used, but that option
- * breaks the ABI anyway.
- */
- if (!streq(lml->ml_name, "cpu_m_pad") &&
- getenv("CTFCONVERT_PERMISSIVE") == NULL) {
- terminate("last cpu_t member before cpu_m is %s; "
- "it must be cpu_m_pad.\n", lml->ml_name);
- }
-
- if ((machcpu = lookup_tdesc(td, "machcpu")) == NULL) {
- machcpu = xcalloc(sizeof (*machcpu));
- machcpu->t_name = xstrdup("machcpu");
- machcpu->t_id = td->td_nextid++;
- machcpu->t_type = FORWARD;
- } else if (machcpu->t_type != STRUCT) {
- return;
- }
-
- debug(3, "Adding cpu_m machcpu %s to cpu struct\n",
- (machcpu->t_type == FORWARD ? "forward" : "struct"));
-
- cpum = xmalloc(sizeof (*cpum));
- cpum->ml_offset = lml->ml_offset + (ptrsize * NBBY);
- cpum->ml_size = 0;
- cpum->ml_name = xstrdup("cpu_m");
- cpum->ml_type = machcpu;
- cpum->ml_next = NULL;
-
- lml->ml_next = cpum;
-}
-
-void
-cvt_fixups(tdata_t *td, size_t ptrsize)
-{
- fix_small_cpu_struct(td, ptrsize);
-}
diff --git a/usr/src/tools/ctf/cvt/hash.c b/usr/src/tools/ctf/cvt/hash.c
deleted file mode 100644
index e3c2978f6e..0000000000
--- a/usr/src/tools/ctf/cvt/hash.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * 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.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Routines for manipulating hash tables
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <sys/types.h>
-#include <sys/sysmacros.h>
-
-#include "hash.h"
-#include "memory.h"
-#include "list.h"
-
-struct hash {
- int h_nbuckets;
- list_t **h_buckets;
-
- int (*h_hashfn)(int, void *);
- int (*h_cmp)(void *, void *);
-};
-
-struct hash_data {
- hash_t *hd_hash;
- int (*hd_fun)();
- void *hd_key;
- void *hd_private;
-
- void *hd_ret;
-};
-
-static int
-hash_def_hash(int nbuckets, uintptr_t data)
-{
- return (data % nbuckets);
-}
-
-static int
-hash_def_cmp(uintptr_t d1, uintptr_t d2)
-{
- return (d1 != d2);
-}
-
-
-int
-hash_name(int nbuckets, const char *name)
-{
- const char *c;
- ulong_t g;
- int h = 0;
-
- for (c = name; *c; c++) {
- h = (h << 4) + *c;
- if ((g = (h & 0xf0000000)) != 0) {
- h ^= (g >> 24);
- h ^= g;
- }
- }
-
- return (h % nbuckets);
-}
-
-hash_t *
-hash_new(int nbuckets, int (*hashfn)(int, void *), int (*cmp)(void *, void *))
-{
- hash_t *hash;
-
- hash = xmalloc(sizeof (hash_t));
- hash->h_buckets = xcalloc(sizeof (list_t *) * nbuckets);
- hash->h_nbuckets = nbuckets;
- hash->h_hashfn = hashfn ? hashfn : (int (*)())hash_def_hash;
- hash->h_cmp = cmp ? cmp : (int (*)())hash_def_cmp;
-
- return (hash);
-}
-
-void
-hash_add(hash_t *hash, void *key)
-{
- int bucket = hash->h_hashfn(hash->h_nbuckets, key);
-
- list_add(&hash->h_buckets[bucket], key);
-}
-
-static int
-hash_add_cb(void *node, void *private)
-{
- hash_add((hash_t *)private, node);
- return (0);
-}
-
-void
-hash_merge(hash_t *to, hash_t *from)
-{
- (void) hash_iter(from, hash_add_cb, to);
-}
-
-static int
-hash_remove_cb(void *key1, void *key2, hash_t *hash)
-{
- return (hash->h_cmp(key1, key2));
-}
-
-void
-hash_remove(hash_t *hash, void *key)
-{
- int bucket = hash->h_hashfn(hash->h_nbuckets, key);
-
- (void) list_remove(&hash->h_buckets[bucket], key,
- (int (*)())hash_remove_cb, hash);
-}
-
-int
-hash_match(hash_t *hash, void *key, int (*fun)(void *, void *),
- void *private)
-{
- int bucket = hash->h_hashfn(hash->h_nbuckets, key);
-
- return (list_iter(hash->h_buckets[bucket], fun, private) < 0);
-}
-
-static int
-hash_find_list_cb(void *node, struct hash_data *hd)
-{
- int cbrc;
- int rc = 0;
-
- if (hd->hd_hash->h_cmp(hd->hd_key, node) == 0) {
- if ((cbrc = hd->hd_fun(node, hd->hd_private)) < 0)
- return (cbrc);
- rc += cbrc;
- }
-
- return (rc);
-}
-
-int
-hash_find_iter(hash_t *hash, void *key, int (*fun)(void *, void *),
- void *private)
-{
- int bucket = hash->h_hashfn(hash->h_nbuckets, key);
- struct hash_data hd;
-
- hd.hd_hash = hash;
- hd.hd_fun = fun;
- hd.hd_key = key;
- hd.hd_private = private;
-
- return (list_iter(hash->h_buckets[bucket], (int (*)())hash_find_list_cb,
- &hd));
-}
-
-/* stop on first match */
-static int
-hash_find_first_cb(void *node, struct hash_data *hd)
-{
- if (hd->hd_hash->h_cmp(hd->hd_key, node) == 0) {
- hd->hd_ret = node;
- return (-1);
- }
-
- return (0);
-}
-
-int
-hash_find(hash_t *hash, void *key, void **value)
-{
- int ret;
- struct hash_data hd;
-
- hd.hd_hash = hash;
- hd.hd_fun = hash_find_first_cb;
- hd.hd_key = key;
-
- ret = hash_match(hash, key, (int (*)())hash_find_first_cb, &hd);
- if (ret && value)
- *value = hd.hd_ret;
-
- return (ret);
-}
-
-int
-hash_iter(hash_t *hash, int (*fun)(void *, void *), void *private)
-{
- int cumrc = 0;
- int cbrc;
- int i;
-
- for (i = 0; i < hash->h_nbuckets; i++) {
- if (hash->h_buckets[i] != NULL) {
- if ((cbrc = list_iter(hash->h_buckets[i], fun,
- private)) < 0)
- return (cbrc);
- cumrc += cbrc;
- }
- }
-
- return (cumrc);
-}
-
-int
-hash_count(hash_t *hash)
-{
- int num, i;
-
- for (num = 0, i = 0; i < hash->h_nbuckets; i++)
- num += list_count(hash->h_buckets[i]);
-
- return (num);
-}
-
-void
-hash_free(hash_t *hash, void (*datafree)(void *, void *), void *private)
-{
- int i;
-
- if (hash == NULL)
- return;
-
- for (i = 0; i < hash->h_nbuckets; i++)
- list_free(hash->h_buckets[i], datafree, private);
- free(hash->h_buckets);
- free(hash);
-}
-
-void
-hash_stats(hash_t *hash, int verbose)
-{
- int min = list_count(hash->h_buckets[0]);
- int minidx = 0;
- int max = min;
- int maxidx = 0;
- int tot = min;
- int count;
- int i;
-
- if (min && verbose)
- printf("%3d: %d\n", 0, min);
- for (i = 1; i < hash->h_nbuckets; i++) {
- count = list_count(hash->h_buckets[i]);
- if (min > count) {
- min = count;
- minidx = i;
- }
- if (max < count) {
- max = count;
- maxidx = i;
- }
- if (count && verbose)
- printf("%3d: %d\n", i, count);
- tot += count;
- }
-
- printf("Hash statistics:\n");
- printf(" Buckets: %d\n", hash->h_nbuckets);
- printf(" Items : %d\n", tot);
- printf(" Min/Max: %d in #%d, %d in #%d\n", min, minidx, max, maxidx);
- printf(" Average: %5.2f\n", (float)tot / (float)hash->h_nbuckets);
-}
diff --git a/usr/src/tools/ctf/cvt/hash.h b/usr/src/tools/ctf/cvt/hash.h
deleted file mode 100644
index 94d93d4e5e..0000000000
--- a/usr/src/tools/ctf/cvt/hash.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef _HASH_H
-#define _HASH_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Routines for manipulating hash tables
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct hash hash_t;
-
-hash_t *hash_new(int, int (*)(int, void *), int (*)(void *, void *));
-void hash_add(hash_t *, void *);
-void hash_merge(hash_t *, hash_t *);
-void hash_remove(hash_t *, void *);
-int hash_find(hash_t *, void *, void **);
-int hash_find_iter(hash_t *, void *, int (*)(void *, void *), void *);
-int hash_iter(hash_t *, int (*)(void *, void *), void *);
-int hash_match(hash_t *, void *, int (*)(void *, void *), void *);
-int hash_count(hash_t *);
-int hash_name(int, const char *);
-void hash_stats(hash_t *, int);
-void hash_free(hash_t *, void (*)(void *, void *), void *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _HASH_H */
diff --git a/usr/src/tools/ctf/cvt/i386/Makefile b/usr/src/tools/ctf/cvt/i386/Makefile
deleted file mode 100644
index 9d3f4c8023..0000000000
--- a/usr/src/tools/ctf/cvt/i386/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# 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.
-#
-
-include ../Makefile.com
-include ../Makefile.targ
-
diff --git a/usr/src/tools/ctf/cvt/iidesc.c b/usr/src/tools/ctf/cvt/iidesc.c
deleted file mode 100644
index 0d75e3f852..0000000000
--- a/usr/src/tools/ctf/cvt/iidesc.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * Routines for manipulating iidesc_t structures
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-
-#include "ctftools.h"
-#include "memory.h"
-#include "list.h"
-#include "hash.h"
-
-typedef struct iidesc_find {
- iidesc_t *iif_tgt;
- iidesc_t *iif_ret;
-} iidesc_find_t;
-
-iidesc_t *
-iidesc_new(char *name)
-{
- iidesc_t *ii;
-
- ii = xcalloc(sizeof (iidesc_t));
- if (name)
- ii->ii_name = xstrdup(name);
-
- return (ii);
-}
-
-int
-iidesc_hash(int nbuckets, void *arg)
-{
- iidesc_t *ii = arg;
- int h = 0;
-
- if (ii->ii_name)
- return (hash_name(nbuckets, ii->ii_name));
-
- return (h);
-}
-
-static int
-iidesc_cmp(iidesc_t *src, iidesc_find_t *find)
-{
- iidesc_t *tgt = find->iif_tgt;
-
- if (src->ii_type != tgt->ii_type ||
- !streq(src->ii_name, tgt->ii_name))
- return (0);
-
- find->iif_ret = src;
-
- return (-1);
-}
-
-void
-iidesc_add(hash_t *hash, iidesc_t *new)
-{
- iidesc_find_t find;
-
- find.iif_tgt = new;
- find.iif_ret = NULL;
-
- (void) hash_match(hash, new, (int (*)())iidesc_cmp, &find);
-
- if (find.iif_ret != NULL) {
- iidesc_t *old = find.iif_ret;
- iidesc_t tmp;
- /* replacing existing one */
- bcopy(old, &tmp, sizeof (tmp));
- bcopy(new, old, sizeof (*old));
- bcopy(&tmp, new, sizeof (*new));
-
- iidesc_free(new);
- return;
- }
-
- hash_add(hash, new);
-}
-
-void
-iter_iidescs_by_name(tdata_t *td, const char *name,
- int (*func)(iidesc_t *, void *), void *data)
-{
- iidesc_t tmpdesc;
- bzero(&tmpdesc, sizeof (iidesc_t));
- tmpdesc.ii_name = (char *)name;
- (void) hash_match(td->td_iihash, &tmpdesc, (int (*)())func, data);
-}
-
-iidesc_t *
-iidesc_dup(iidesc_t *src)
-{
- iidesc_t *tgt;
-
- tgt = xmalloc(sizeof (iidesc_t));
- bcopy(src, tgt, sizeof (iidesc_t));
-
- tgt->ii_name = src->ii_name ? xstrdup(src->ii_name) : NULL;
- tgt->ii_owner = src->ii_owner ? xstrdup(src->ii_owner) : NULL;
-
- if (tgt->ii_nargs) {
- tgt->ii_args = xmalloc(sizeof (tdesc_t *) * tgt->ii_nargs);
- bcopy(src->ii_args, tgt->ii_args,
- sizeof (tdesc_t *) * tgt->ii_nargs);
- }
-
- return (tgt);
-}
-
-iidesc_t *
-iidesc_dup_rename(iidesc_t *src, char const *name, char const *owner)
-{
- iidesc_t *tgt = iidesc_dup(src);
- free(tgt->ii_name);
- free(tgt->ii_owner);
-
- tgt->ii_name = name ? xstrdup(name) : NULL;
- tgt->ii_owner = owner ? xstrdup(owner) : NULL;
-
- return (tgt);
-}
-
-/*ARGSUSED*/
-void
-iidesc_free_cb(void *ptr, void *private)
-{
- iidesc_t *idp = ptr;
-
- free(idp->ii_name);
- free(idp->ii_args);
- free(idp->ii_owner);
- free(idp);
-}
-
-void
-iidesc_free(iidesc_t *idp)
-{
- iidesc_free_cb(idp, NULL);
-}
-
-int
-iidesc_dump(iidesc_t *ii)
-{
- printf("type: %d name %s\n", ii->ii_type,
- (ii->ii_name ? ii->ii_name : "(anon)"));
-
- return (0);
-}
-
-int
-iidesc_count_type(void *data, void *private)
-{
- iidesc_t *ii = data;
- iitype_t match = (iitype_t)private;
-
- return (ii->ii_type == match);
-}
-
-void
-iidesc_stats(hash_t *ii)
-{
- printf("GFun: %5d SFun: %5d GVar: %5d SVar: %5d T %5d SOU: %5d\n",
- hash_iter(ii, iidesc_count_type, (void *)II_GFUN),
- hash_iter(ii, iidesc_count_type, (void *)II_SFUN),
- hash_iter(ii, iidesc_count_type, (void *)II_GVAR),
- hash_iter(ii, iidesc_count_type, (void *)II_SVAR),
- hash_iter(ii, iidesc_count_type, (void *)II_TYPE),
- hash_iter(ii, iidesc_count_type, (void *)II_SOU));
-}
diff --git a/usr/src/tools/ctf/cvt/input.c b/usr/src/tools/ctf/cvt/input.c
deleted file mode 100644
index d901e5340b..0000000000
--- a/usr/src/tools/ctf/cvt/input.c
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * 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.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Routines for retrieving CTF data from a .SUNW_ctf ELF section
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <gelf.h>
-#include <strings.h>
-#include <sys/types.h>
-
-#include "ctftools.h"
-#include "memory.h"
-#include "symbol.h"
-
-typedef int read_cb_f(tdata_t *, char *, void *);
-
-/*
- * Return the source types that the object was generated from.
- */
-source_types_t
-built_source_types(Elf *elf, char const *file)
-{
- source_types_t types = SOURCE_NONE;
- symit_data_t *si;
-
- if ((si = symit_new(elf, file)) == NULL)
- return (SOURCE_NONE);
-
- while (symit_next(si, STT_FILE) != NULL) {
- char *name = symit_name(si);
- size_t len = strlen(name);
- if (len < 2 || name[len - 2] != '.') {
- types |= SOURCE_UNKNOWN;
- continue;
- }
-
- switch (name[len - 1]) {
- case 'c':
- types |= SOURCE_C;
- break;
- case 'h':
- /* ignore */
- break;
- case 's':
- types |= SOURCE_S;
- break;
- default:
- types |= SOURCE_UNKNOWN;
- }
- }
-
- symit_free(si);
- return (types);
-}
-
-static int
-read_file(Elf *elf, char *file, char *label, read_cb_f *func, void *arg,
- int require_ctf)
-{
- Elf_Scn *ctfscn;
- Elf_Data *ctfdata;
- symit_data_t *si = NULL;
- int ctfscnidx;
- tdata_t *td;
-
- if ((ctfscnidx = findelfsecidx(elf, file, ".SUNW_ctf")) < 0) {
- if (require_ctf &&
- (built_source_types(elf, file) & SOURCE_C)) {
- terminate("Input file %s was partially built from "
- "C sources, but no CTF data was present\n", file);
- }
- return (0);
- }
-
- if ((ctfscn = elf_getscn(elf, ctfscnidx)) == NULL ||
- (ctfdata = elf_getdata(ctfscn, NULL)) == NULL)
- elfterminate(file, "Cannot read CTF section");
-
- /* Reconstruction of type tree */
- if ((si = symit_new(elf, file)) == NULL) {
- warning("%s has no symbol table - skipping", file);
- return (0);
- }
-
- td = ctf_load(file, ctfdata->d_buf, ctfdata->d_size, si, label);
- tdata_build_hashes(td);
-
- symit_free(si);
-
- if (td != NULL) {
- if (func(td, file, arg) < 0)
- return (-1);
- else
- return (1);
- }
- return (0);
-}
-
-static int
-read_archive(int fd, Elf *elf, char *file, char *label, read_cb_f *func,
- void *arg, int require_ctf)
-{
- Elf *melf;
- Elf_Cmd cmd = ELF_C_READ;
- Elf_Arhdr *arh;
- int secnum = 1, found = 0;
-
- while ((melf = elf_begin(fd, cmd, elf)) != NULL) {
- int rc = 0;
-
- if ((arh = elf_getarhdr(melf)) == NULL) {
- elfterminate(file, "Can't get archive header for "
- "member %d", secnum);
- }
-
- /* skip special sections - their names begin with "/" */
- if (*arh->ar_name != '/') {
- size_t memlen = strlen(file) + 1 +
- strlen(arh->ar_name) + 1 + 1;
- char *memname = xmalloc(memlen);
-
- snprintf(memname, memlen, "%s(%s)", file, arh->ar_name);
-
- switch (elf_kind(melf)) {
- case ELF_K_AR:
- rc = read_archive(fd, melf, memname, label,
- func, arg, require_ctf);
- break;
- case ELF_K_ELF:
- rc = read_file(melf, memname, label,
- func, arg, require_ctf);
- break;
- default:
- terminate("%s: Unknown elf kind %d\n",
- memname, elf_kind(melf));
- }
-
- free(memname);
- }
-
- cmd = elf_next(melf);
- (void) elf_end(melf);
- secnum++;
-
- if (rc < 0)
- return (rc);
- else
- found += rc;
- }
-
- return (found);
-}
-
-static int
-read_ctf_common(char *file, char *label, read_cb_f *func, void *arg,
- int require_ctf)
-{
- Elf *elf;
- int found = 0;
- int fd;
-
- debug(3, "Reading %s (label %s)\n", file, (label ? label : "NONE"));
-
- (void) elf_version(EV_CURRENT);
-
- if ((fd = open(file, O_RDONLY)) < 0)
- terminate("%s: Cannot open for reading", file);
- if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL)
- elfterminate(file, "Cannot read");
-
- switch (elf_kind(elf)) {
- case ELF_K_AR:
- found = read_archive(fd, elf, file, label,
- func, arg, require_ctf);
- break;
-
- case ELF_K_ELF:
- found = read_file(elf, file, label,
- func, arg, require_ctf);
- break;
-
- default:
- terminate("%s: Unknown elf kind %d\n", file, elf_kind(elf));
- }
-
- (void) elf_end(elf);
- (void) close(fd);
-
- return (found);
-}
-
-/*ARGSUSED*/
-int
-read_ctf_save_cb(tdata_t *td, char *name, void *retp)
-{
- tdata_t **tdp = retp;
-
- *tdp = td;
-
- return (1);
-}
-
-int
-read_ctf(char **files, int n, char *label, read_cb_f *func, void *private,
- int require_ctf)
-{
- int found;
- int i, rc;
-
- for (i = 0, found = 0; i < n; i++) {
- if ((rc = read_ctf_common(files[i], label, func,
- private, require_ctf)) < 0)
- return (rc);
- found += rc;
- }
-
- return (found);
-}
-
-static int
-count_archive(int fd, Elf *elf, char *file)
-{
- Elf *melf;
- Elf_Cmd cmd = ELF_C_READ;
- Elf_Arhdr *arh;
- int nfiles = 0, err = 0;
-
- while ((melf = elf_begin(fd, cmd, elf)) != NULL) {
- if ((arh = elf_getarhdr(melf)) == NULL) {
- warning("Can't process input archive %s\n",
- file);
- err++;
- }
-
- if (*arh->ar_name != '/')
- nfiles++;
-
- cmd = elf_next(melf);
- (void) elf_end(melf);
- }
-
- if (err > 0)
- return (-1);
-
- return (nfiles);
-}
-
-int
-count_files(char **files, int n)
-{
- int nfiles = 0, err = 0;
- Elf *elf;
- int fd, rc, i;
-
- (void) elf_version(EV_CURRENT);
-
- for (i = 0; i < n; i++) {
- char *file = files[i];
-
- if ((fd = open(file, O_RDONLY)) < 0) {
- warning("Can't read input file %s", file);
- err++;
- continue;
- }
-
- if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
- warning("Can't open input file %s: %s\n", file,
- elf_errmsg(-1));
- err++;
- (void) close(fd);
- continue;
- }
-
- switch (elf_kind(elf)) {
- case ELF_K_AR:
- if ((rc = count_archive(fd, elf, file)) < 0)
- err++;
- else
- nfiles += rc;
- break;
- case ELF_K_ELF:
- nfiles++;
- break;
- default:
- warning("Input file %s is corrupt\n", file);
- err++;
- }
-
- (void) elf_end(elf);
- (void) close(fd);
- }
-
- if (err > 0)
- return (-1);
-
- debug(2, "Found %d files in %d input files\n", nfiles, n);
-
- return (nfiles);
-}
-
-struct symit_data {
- GElf_Shdr si_shdr;
- Elf_Data *si_symd;
- Elf_Data *si_strd;
- GElf_Sym si_cursym;
- char *si_curname;
- char *si_curfile;
- int si_nument;
- int si_next;
-};
-
-symit_data_t *
-symit_new(Elf *elf, const char *file)
-{
- symit_data_t *si;
- Elf_Scn *scn;
- int symtabidx;
-
- if ((symtabidx = findelfsecidx(elf, file, ".symtab")) < 0)
- return (NULL);
-
- si = xcalloc(sizeof (symit_data_t));
-
- if ((scn = elf_getscn(elf, symtabidx)) == NULL ||
- gelf_getshdr(scn, &si->si_shdr) == NULL ||
- (si->si_symd = elf_getdata(scn, NULL)) == NULL)
- elfterminate(file, "Cannot read .symtab");
-
- if ((scn = elf_getscn(elf, si->si_shdr.sh_link)) == NULL ||
- (si->si_strd = elf_getdata(scn, NULL)) == NULL)
- elfterminate(file, "Cannot read strings for .symtab");
-
- si->si_nument = si->si_shdr.sh_size / si->si_shdr.sh_entsize;
-
- return (si);
-}
-
-void
-symit_free(symit_data_t *si)
-{
- free(si);
-}
-
-void
-symit_reset(symit_data_t *si)
-{
- si->si_next = 0;
-}
-
-char *
-symit_curfile(symit_data_t *si)
-{
- return (si->si_curfile);
-}
-
-GElf_Sym *
-symit_next(symit_data_t *si, int type)
-{
- GElf_Sym sym;
- int check_sym = (type == STT_OBJECT || type == STT_FUNC);
-
- for (; si->si_next < si->si_nument; si->si_next++) {
- gelf_getsym(si->si_symd, si->si_next, &si->si_cursym);
- gelf_getsym(si->si_symd, si->si_next, &sym);
- si->si_curname = (caddr_t)si->si_strd->d_buf + sym.st_name;
-
- if (GELF_ST_TYPE(sym.st_info) == STT_FILE)
- si->si_curfile = si->si_curname;
-
- if (GELF_ST_TYPE(sym.st_info) != type ||
- sym.st_shndx == SHN_UNDEF)
- continue;
-
- if (check_sym && ignore_symbol(&sym, si->si_curname))
- continue;
-
- si->si_next++;
-
- return (&si->si_cursym);
- }
-
- return (NULL);
-}
-
-char *
-symit_name(symit_data_t *si)
-{
- return (si->si_curname);
-}
diff --git a/usr/src/tools/ctf/cvt/merge.c b/usr/src/tools/ctf/cvt/merge.c
deleted file mode 100644
index 2af28b65a2..0000000000
--- a/usr/src/tools/ctf/cvt/merge.c
+++ /dev/null
@@ -1,1140 +0,0 @@
-/*
- * 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.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * This file contains routines that merge one tdata_t tree, called the child,
- * into another, called the parent. Note that these names are used mainly for
- * convenience and to represent the direction of the merge. They are not meant
- * to imply any relationship between the tdata_t graphs prior to the merge.
- *
- * tdata_t structures contain two main elements - a hash of iidesc_t nodes, and
- * a directed graph of tdesc_t nodes, pointed to by the iidesc_t nodes. Simply
- * put, we merge the tdesc_t graphs, followed by the iidesc_t nodes, and then we
- * clean up loose ends.
- *
- * The algorithm is as follows:
- *
- * 1. Mapping iidesc_t nodes
- *
- * For each child iidesc_t node, we first try to map its tdesc_t subgraph
- * against the tdesc_t graph in the parent. For each node in the child subgraph
- * that exists in the parent, a mapping between the two (between their type IDs)
- * is established. For the child nodes that cannot be mapped onto existing
- * parent nodes, a mapping is established between the child node ID and a
- * newly-allocated ID that the node will use when it is re-created in the
- * parent. These unmappable nodes are added to the md_tdtba (tdesc_t To Be
- * Added) hash, which tracks nodes that need to be created in the parent.
- *
- * If all of the nodes in the subgraph for an iidesc_t in the child can be
- * mapped to existing nodes in the parent, then we can try to map the child
- * iidesc_t onto an iidesc_t in the parent. If we cannot find an equivalent
- * iidesc_t, or if we were not able to completely map the tdesc_t subgraph(s),
- * then we add this iidesc_t to the md_iitba (iidesc_t To Be Added) list. This
- * list tracks iidesc_t nodes that are to be created in the parent.
- *
- * While visiting the tdesc_t nodes, we may discover a forward declaration (a
- * FORWARD tdesc_t) in the parent that is resolved in the child. That is, there
- * may be a structure or union definition in the child with the same name as the
- * forward declaration in the parent. If we find such a node, we record an
- * association in the md_fdida (Forward => Definition ID Association) list
- * between the parent ID of the forward declaration and the ID that the
- * definition will use when re-created in the parent.
- *
- * 2. Creating new tdesc_t nodes (the md_tdtba hash)
- *
- * We have now attempted to map all tdesc_t nodes from the child into the
- * parent, and have, in md_tdtba, a hash of all tdesc_t nodes that need to be
- * created (or, as we so wittily call it, conjured) in the parent. We iterate
- * through this hash, creating the indicated tdesc_t nodes. For a given tdesc_t
- * node, conjuring requires two steps - the copying of the common tdesc_t data
- * (name, type, etc) from the child node, and the creation of links from the
- * newly-created node to the parent equivalents of other tdesc_t nodes pointed
- * to by node being conjured. Note that in some cases, the targets of these
- * links will be on the md_tdtba hash themselves, and may not have been created
- * yet. As such, we can't establish the links from these new nodes into the
- * parent graph. We therefore conjure them with links to nodes in the *child*
- * graph, and add pointers to the links to be created to the md_tdtbr (tdesc_t
- * To Be Remapped) hash. For example, a POINTER tdesc_t that could not be
- * resolved would have its &tdesc_t->t_tdesc added to md_tdtbr.
- *
- * 3. Creating new iidesc_t nodes (the md_iitba list)
- *
- * When we have completed step 2, all tdesc_t nodes have been created (or
- * already existed) in the parent. Some of them may have incorrect links (the
- * members of the md_tdtbr list), but they've all been created. As such, we can
- * create all of the iidesc_t nodes, as we can attach the tdesc_t subgraph
- * pointers correctly. We create each node, and attach the pointers to the
- * appropriate parts of the parent tdesc_t graph.
- *
- * 4. Resolving newly-created tdesc_t node links (the md_tdtbr list)
- *
- * As in step 3, we rely on the fact that all of the tdesc_t nodes have been
- * created. Each entry in the md_tdtbr list is a pointer to where a link into
- * the parent will be established. As saved in the md_tdtbr list, these
- * pointers point into the child tdesc_t subgraph. We can thus get the target
- * type ID from the child, look at the ID mapping to determine the desired link
- * target, and redirect the link accordingly.
- *
- * 5. Parent => child forward declaration resolution
- *
- * If entries were made in the md_fdida list in step 1, we have forward
- * declarations in the parent that need to be resolved to their definitions
- * re-created in step 2 from the child. Using the md_fdida list, we can locate
- * the definition for the forward declaration, and we can redirect all inbound
- * edges to the forward declaration node to the actual definition.
- *
- * A pox on the house of anyone who changes the algorithm without updating
- * this comment.
- */
-
-#include <stdio.h>
-#include <strings.h>
-#include <assert.h>
-#include <pthread.h>
-
-#include "ctf_headers.h"
-#include "ctftools.h"
-#include "list.h"
-#include "alist.h"
-#include "memory.h"
-#include "traverse.h"
-
-typedef struct equiv_data equiv_data_t;
-typedef struct merge_cb_data merge_cb_data_t;
-
-/*
- * There are two traversals in this file, for equivalency and for tdesc_t
- * re-creation, that do not fit into the tdtraverse() framework. We have our
- * own traversal mechanism and ops vector here for those two cases.
- */
-typedef struct tdesc_ops {
- char *name;
- int (*equiv)(tdesc_t *, tdesc_t *, equiv_data_t *);
- tdesc_t *(*conjure)(tdesc_t *, int, merge_cb_data_t *);
-} tdesc_ops_t;
-extern tdesc_ops_t tdesc_ops[];
-
-/*
- * The workhorse structure of tdata_t merging. Holds all lists of nodes to be
- * processed during various phases of the merge algorithm.
- */
-struct merge_cb_data {
- tdata_t *md_parent;
- tdata_t *md_tgt;
- alist_t *md_ta; /* Type Association */
- alist_t *md_fdida; /* Forward -> Definition ID Association */
- list_t **md_iitba; /* iidesc_t nodes To Be Added to the parent */
- hash_t *md_tdtba; /* tdesc_t nodes To Be Added to the parent */
- list_t **md_tdtbr; /* tdesc_t nodes To Be Remapped */
- int md_flags;
-}; /* merge_cb_data_t */
-
-/*
- * When we first create a tdata_t from stabs data, we will have duplicate nodes.
- * Normal merges, however, assume that the child tdata_t is already self-unique,
- * and for speed reasons do not attempt to self-uniquify. If this flag is set,
- * the merge algorithm will self-uniquify by avoiding the insertion of
- * duplicates in the md_tdtdba list.
- */
-#define MCD_F_SELFUNIQUIFY 0x1
-
-/*
- * When we merge the CTF data for the modules, we don't want it to contain any
- * data that can be found in the reference module (usually genunix). If this
- * flag is set, we're doing a merge between the fully merged tdata_t for this
- * module and the tdata_t for the reference module, with the data unique to this
- * module ending up in a third tdata_t. It is this third tdata_t that will end
- * up in the .SUNW_ctf section for the module.
- */
-#define MCD_F_REFMERGE 0x2
-
-/*
- * Mapping of child type IDs to parent type IDs
- */
-
-static void
-add_mapping(alist_t *ta, tid_t srcid, tid_t tgtid)
-{
- debug(3, "Adding mapping %u => %u\n", srcid, tgtid);
-
- assert(!alist_find(ta, (void *)srcid, NULL));
- assert(srcid != 0 && tgtid != 0);
-
- alist_add(ta, (void *)srcid, (void *)tgtid);
-}
-
-static tid_t
-get_mapping(alist_t *ta, int srcid)
-{
- long ltgtid;
-
- if (alist_find(ta, (void *)srcid, (void **)&ltgtid))
- return ((int)ltgtid);
- else
- return (0);
-}
-
-/*
- * Determining equivalence of tdesc_t subgraphs
- */
-
-struct equiv_data {
- alist_t *ed_ta;
- tdesc_t *ed_node;
- tdesc_t *ed_tgt;
-
- int ed_clear_mark;
- int ed_cur_mark;
- int ed_selfuniquify;
-}; /* equiv_data_t */
-
-static int equiv_node(tdesc_t *, tdesc_t *, equiv_data_t *);
-
-/*ARGSUSED2*/
-static int
-equiv_intrinsic(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed)
-{
- intr_t *si = stdp->t_intr;
- intr_t *ti = ttdp->t_intr;
-
- if (si->intr_type != ti->intr_type ||
- si->intr_signed != ti->intr_signed ||
- si->intr_offset != ti->intr_offset ||
- si->intr_nbits != ti->intr_nbits)
- return (0);
-
- if (si->intr_type == INTR_INT &&
- si->intr_iformat != ti->intr_iformat)
- return (0);
- else if (si->intr_type == INTR_REAL &&
- si->intr_fformat != ti->intr_fformat)
- return (0);
-
- return (1);
-}
-
-static int
-equiv_plain(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed)
-{
- return (equiv_node(stdp->t_tdesc, ttdp->t_tdesc, ed));
-}
-
-static int
-equiv_function(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed)
-{
- fndef_t *fn1 = stdp->t_fndef, *fn2 = ttdp->t_fndef;
- int i;
-
- if (fn1->fn_nargs != fn2->fn_nargs ||
- fn1->fn_vargs != fn2->fn_vargs)
- return (0);
-
- if (!equiv_node(fn1->fn_ret, fn2->fn_ret, ed))
- return (0);
-
- for (i = 0; i < fn1->fn_nargs; i++) {
- if (!equiv_node(fn1->fn_args[i], fn2->fn_args[i], ed))
- return (0);
- }
-
- return (1);
-}
-
-static int
-equiv_array(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed)
-{
- ardef_t *ar1 = stdp->t_ardef, *ar2 = ttdp->t_ardef;
-
- if (!equiv_node(ar1->ad_contents, ar2->ad_contents, ed) ||
- !equiv_node(ar1->ad_idxtype, ar2->ad_idxtype, ed))
- return (0);
-
- if (ar1->ad_nelems != ar2->ad_nelems)
- return (0);
-
- return (1);
-}
-
-static int
-equiv_su(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed)
-{
- mlist_t *ml1 = stdp->t_members, *ml2 = ttdp->t_members;
- mlist_t *olm1 = NULL;
-
- while (ml1 && ml2) {
- if (ml1->ml_offset != ml2->ml_offset ||
- strcmp(ml1->ml_name, ml2->ml_name) != 0)
- return (0);
-
- /*
- * Don't do the recursive equivalency checking more than
- * we have to.
- */
- if (olm1 == NULL || olm1->ml_type->t_id != ml1->ml_type->t_id) {
- if (ml1->ml_size != ml2->ml_size ||
- !equiv_node(ml1->ml_type, ml2->ml_type, ed))
- return (0);
- }
-
- olm1 = ml1;
- ml1 = ml1->ml_next;
- ml2 = ml2->ml_next;
- }
-
- if (ml1 || ml2)
- return (0);
-
- return (1);
-}
-
-/*ARGSUSED2*/
-static int
-equiv_enum(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed)
-{
- elist_t *el1 = stdp->t_emem;
- elist_t *el2 = ttdp->t_emem;
-
- while (el1 && el2) {
- if (el1->el_number != el2->el_number ||
- strcmp(el1->el_name, el2->el_name) != 0)
- return (0);
-
- el1 = el1->el_next;
- el2 = el2->el_next;
- }
-
- if (el1 || el2)
- return (0);
-
- return (1);
-}
-
-/*ARGSUSED*/
-static int
-equiv_assert(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed)
-{
- /* foul, evil, and very bad - this is a "shouldn't happen" */
- assert(1 == 0);
-
- return (0);
-}
-
-static int
-fwd_equiv(tdesc_t *ctdp, tdesc_t *mtdp)
-{
- tdesc_t *defn = (ctdp->t_type == FORWARD ? mtdp : ctdp);
-
- return (defn->t_type == STRUCT || defn->t_type == UNION);
-}
-
-static int
-equiv_node(tdesc_t *ctdp, tdesc_t *mtdp, equiv_data_t *ed)
-{
- int (*equiv)();
- int mapping;
-
- if (ctdp->t_emark > ed->ed_clear_mark ||
- mtdp->t_emark > ed->ed_clear_mark)
- return (ctdp->t_emark == mtdp->t_emark);
-
- /*
- * In normal (non-self-uniquify) mode, we don't want to do equivalency
- * checking on a subgraph that has already been checked. If a mapping
- * has already been established for a given child node, we can simply
- * compare the mapping for the child node with the ID of the parent
- * node. If we are in self-uniquify mode, then we're comparing two
- * subgraphs within the child graph, and thus need to ignore any
- * type mappings that have been created, as they are only valid into the
- * parent.
- */
- if ((mapping = get_mapping(ed->ed_ta, ctdp->t_id)) > 0 &&
- mapping == mtdp->t_id && !ed->ed_selfuniquify)
- return (1);
-
- if (!streq(ctdp->t_name, mtdp->t_name))
- return (0);
-
- if (ctdp->t_type != mtdp->t_type) {
- if (ctdp->t_type == FORWARD || mtdp->t_type == FORWARD)
- return (fwd_equiv(ctdp, mtdp));
- else
- return (0);
- }
-
- ctdp->t_emark = ed->ed_cur_mark;
- mtdp->t_emark = ed->ed_cur_mark;
- ed->ed_cur_mark++;
-
- if ((equiv = tdesc_ops[ctdp->t_type].equiv) != NULL)
- return (equiv(ctdp, mtdp, ed));
-
- return (1);
-}
-
-/*
- * We perform an equivalency check on two subgraphs by traversing through them
- * in lockstep. If a given node is equivalent in both the parent and the child,
- * we mark it in both subgraphs, using the t_emark field, with a monotonically
- * increasing number. If, in the course of the traversal, we reach a node that
- * we have visited and numbered during this equivalency check, we have a cycle.
- * If the previously-visited nodes don't have the same emark, then the edges
- * that brought us to these nodes are not equivalent, and so the check ends.
- * If the emarks are the same, the edges are equivalent. We then backtrack and
- * continue the traversal. If we have exhausted all edges in the subgraph, and
- * have not found any inequivalent nodes, then the subgraphs are equivalent.
- */
-static int
-equiv_cb(void *bucket, void *arg)
-{
- equiv_data_t *ed = arg;
- tdesc_t *mtdp = bucket;
- tdesc_t *ctdp = ed->ed_node;
-
- ed->ed_clear_mark = ed->ed_cur_mark + 1;
- ed->ed_cur_mark = ed->ed_clear_mark + 1;
-
- if (equiv_node(ctdp, mtdp, ed)) {
- debug(3, "equiv_node matched %d %d\n", ctdp->t_id, mtdp->t_id);
- ed->ed_tgt = mtdp;
- /* matched. stop looking */
- return (-1);
- }
-
- return (0);
-}
-
-/*ARGSUSED1*/
-static int
-map_td_tree_pre(tdesc_t *ctdp, tdesc_t **ctdpp, void *private)
-{
- merge_cb_data_t *mcd = private;
-
- if (get_mapping(mcd->md_ta, ctdp->t_id) > 0)
- return (0);
-
- return (1);
-}
-
-/*ARGSUSED1*/
-static int
-map_td_tree_post(tdesc_t *ctdp, tdesc_t **ctdpp, void *private)
-{
- merge_cb_data_t *mcd = private;
- equiv_data_t ed;
-
- ed.ed_ta = mcd->md_ta;
- ed.ed_clear_mark = mcd->md_parent->td_curemark;
- ed.ed_cur_mark = mcd->md_parent->td_curemark + 1;
- ed.ed_node = ctdp;
- ed.ed_selfuniquify = 0;
-
- debug(3, "map_td_tree_post on %d %s\n", ctdp->t_id, tdesc_name(ctdp));
-
- if (hash_find_iter(mcd->md_parent->td_layouthash, ctdp,
- equiv_cb, &ed) < 0) {
- /* We found an equivalent node */
- if (ed.ed_tgt->t_type == FORWARD && ctdp->t_type != FORWARD) {
- int id = mcd->md_tgt->td_nextid++;
-
- debug(3, "Creating new defn type %d\n", id);
- add_mapping(mcd->md_ta, ctdp->t_id, id);
- alist_add(mcd->md_fdida, (void *)(ulong_t)ed.ed_tgt,
- (void *)(ulong_t)id);
- hash_add(mcd->md_tdtba, ctdp);
- } else
- add_mapping(mcd->md_ta, ctdp->t_id, ed.ed_tgt->t_id);
-
- } else if (debug_level > 1 && hash_iter(mcd->md_parent->td_idhash,
- equiv_cb, &ed) < 0) {
- /*
- * We didn't find an equivalent node by looking through the
- * layout hash, but we somehow found it by performing an
- * exhaustive search through the entire graph. This usually
- * means that the "name" hash function is broken.
- */
- aborterr("Second pass for %d (%s) == %d\n", ctdp->t_id,
- tdesc_name(ctdp), ed.ed_tgt->t_id);
- } else {
- int id = mcd->md_tgt->td_nextid++;
-
- debug(3, "Creating new type %d\n", id);
- add_mapping(mcd->md_ta, ctdp->t_id, id);
- hash_add(mcd->md_tdtba, ctdp);
- }
-
- mcd->md_parent->td_curemark = ed.ed_cur_mark + 1;
-
- return (1);
-}
-
-/*ARGSUSED1*/
-static int
-map_td_tree_self_post(tdesc_t *ctdp, tdesc_t **ctdpp, void *private)
-{
- merge_cb_data_t *mcd = private;
- equiv_data_t ed;
-
- ed.ed_ta = mcd->md_ta;
- ed.ed_clear_mark = mcd->md_parent->td_curemark;
- ed.ed_cur_mark = mcd->md_parent->td_curemark + 1;
- ed.ed_node = ctdp;
- ed.ed_selfuniquify = 1;
- ed.ed_tgt = NULL;
-
- if (hash_find_iter(mcd->md_tdtba, ctdp, equiv_cb, &ed) < 0) {
- debug(3, "Self check found %d in %d\n", ctdp->t_id,
- ed.ed_tgt->t_id);
- add_mapping(mcd->md_ta, ctdp->t_id,
- get_mapping(mcd->md_ta, ed.ed_tgt->t_id));
- } else if (debug_level > 1 && hash_iter(mcd->md_tdtba,
- equiv_cb, &ed) < 0) {
- /*
- * We didn't find an equivalent node using the quick way (going
- * through the hash normally), but we did find it by iterating
- * through the entire hash. This usually means that the hash
- * function is broken.
- */
- aborterr("Self-unique second pass for %d (%s) == %d\n",
- ctdp->t_id, tdesc_name(ctdp), ed.ed_tgt->t_id);
- } else {
- int id = mcd->md_tgt->td_nextid++;
-
- debug(3, "Creating new type %d\n", id);
- add_mapping(mcd->md_ta, ctdp->t_id, id);
- hash_add(mcd->md_tdtba, ctdp);
- }
-
- mcd->md_parent->td_curemark = ed.ed_cur_mark + 1;
-
- return (1);
-}
-
-static tdtrav_cb_f map_pre[] = {
- NULL,
- map_td_tree_pre, /* intrinsic */
- map_td_tree_pre, /* pointer */
- map_td_tree_pre, /* array */
- map_td_tree_pre, /* function */
- map_td_tree_pre, /* struct */
- map_td_tree_pre, /* union */
- map_td_tree_pre, /* enum */
- map_td_tree_pre, /* forward */
- map_td_tree_pre, /* typedef */
- tdtrav_assert, /* typedef_unres */
- map_td_tree_pre, /* volatile */
- map_td_tree_pre, /* const */
- map_td_tree_pre /* restrict */
-};
-
-static tdtrav_cb_f map_post[] = {
- NULL,
- map_td_tree_post, /* intrinsic */
- map_td_tree_post, /* pointer */
- map_td_tree_post, /* array */
- map_td_tree_post, /* function */
- map_td_tree_post, /* struct */
- map_td_tree_post, /* union */
- map_td_tree_post, /* enum */
- map_td_tree_post, /* forward */
- map_td_tree_post, /* typedef */
- tdtrav_assert, /* typedef_unres */
- map_td_tree_post, /* volatile */
- map_td_tree_post, /* const */
- map_td_tree_post /* restrict */
-};
-
-static tdtrav_cb_f map_self_post[] = {
- NULL,
- map_td_tree_self_post, /* intrinsic */
- map_td_tree_self_post, /* pointer */
- map_td_tree_self_post, /* array */
- map_td_tree_self_post, /* function */
- map_td_tree_self_post, /* struct */
- map_td_tree_self_post, /* union */
- map_td_tree_self_post, /* enum */
- map_td_tree_self_post, /* forward */
- map_td_tree_self_post, /* typedef */
- tdtrav_assert, /* typedef_unres */
- map_td_tree_self_post, /* volatile */
- map_td_tree_self_post, /* const */
- map_td_tree_self_post /* restrict */
-};
-
-/*
- * Determining equivalence of iidesc_t nodes
- */
-
-typedef struct iifind_data {
- iidesc_t *iif_template;
- alist_t *iif_ta;
- int iif_newidx;
- int iif_refmerge;
-} iifind_data_t;
-
-/*
- * Check to see if this iidesc_t (node) - the current one on the list we're
- * iterating through - matches the target one (iif->iif_template). Return -1
- * if it matches, to stop the iteration.
- */
-static int
-iidesc_match(void *data, void *arg)
-{
- iidesc_t *node = data;
- iifind_data_t *iif = arg;
- int i;
-
- if (node->ii_type != iif->iif_template->ii_type ||
- !streq(node->ii_name, iif->iif_template->ii_name) ||
- node->ii_dtype->t_id != iif->iif_newidx)
- return (0);
-
- if ((node->ii_type == II_SVAR || node->ii_type == II_SFUN) &&
- !streq(node->ii_owner, iif->iif_template->ii_owner))
- return (0);
-
- if (node->ii_nargs != iif->iif_template->ii_nargs)
- return (0);
-
- for (i = 0; i < node->ii_nargs; i++) {
- if (get_mapping(iif->iif_ta,
- iif->iif_template->ii_args[i]->t_id) !=
- node->ii_args[i]->t_id)
- return (0);
- }
-
- if (iif->iif_refmerge) {
- switch (iif->iif_template->ii_type) {
- case II_GFUN:
- case II_SFUN:
- case II_GVAR:
- case II_SVAR:
- debug(3, "suppressing duping of %d %s from %s\n",
- iif->iif_template->ii_type,
- iif->iif_template->ii_name,
- (iif->iif_template->ii_owner ?
- iif->iif_template->ii_owner : "NULL"));
- return (0);
- case II_NOT:
- case II_PSYM:
- case II_SOU:
- case II_TYPE:
- break;
- }
- }
-
- return (-1);
-}
-
-static int
-merge_type_cb(void *data, void *arg)
-{
- iidesc_t *sii = data;
- merge_cb_data_t *mcd = arg;
- iifind_data_t iif;
- tdtrav_cb_f *post;
-
- post = (mcd->md_flags & MCD_F_SELFUNIQUIFY ? map_self_post : map_post);
-
- /* Map the tdesc nodes */
- (void) iitraverse(sii, &mcd->md_parent->td_curvgen, NULL, map_pre, post,
- mcd);
-
- /* Map the iidesc nodes */
- iif.iif_template = sii;
- iif.iif_ta = mcd->md_ta;
- iif.iif_newidx = get_mapping(mcd->md_ta, sii->ii_dtype->t_id);
- iif.iif_refmerge = (mcd->md_flags & MCD_F_REFMERGE);
-
- if (hash_match(mcd->md_parent->td_iihash, sii, iidesc_match,
- &iif) == 1)
- /* successfully mapped */
- return (1);
-
- debug(3, "tba %s (%d)\n", (sii->ii_name ? sii->ii_name : "(anon)"),
- sii->ii_type);
-
- list_add(mcd->md_iitba, sii);
-
- return (0);
-}
-
-static int
-remap_node(tdesc_t **tgtp, tdesc_t *oldtgt, int selftid, tdesc_t *newself,
- merge_cb_data_t *mcd)
-{
- tdesc_t *tgt = NULL;
- tdesc_t template;
- int oldid = oldtgt->t_id;
-
- if (oldid == selftid) {
- *tgtp = newself;
- return (1);
- }
-
- if ((template.t_id = get_mapping(mcd->md_ta, oldid)) == 0)
- aborterr("failed to get mapping for tid %d\n", oldid);
-
- if (!hash_find(mcd->md_parent->td_idhash, (void *)&template,
- (void *)&tgt) && (!(mcd->md_flags & MCD_F_REFMERGE) ||
- !hash_find(mcd->md_tgt->td_idhash, (void *)&template,
- (void *)&tgt))) {
- debug(3, "Remap couldn't find %d (from %d)\n", template.t_id,
- oldid);
- *tgtp = oldtgt;
- list_add(mcd->md_tdtbr, tgtp);
- return (0);
- }
-
- *tgtp = tgt;
- return (1);
-}
-
-static tdesc_t *
-conjure_template(tdesc_t *old, int newselfid)
-{
- tdesc_t *new = xcalloc(sizeof (tdesc_t));
-
- new->t_name = old->t_name ? xstrdup(old->t_name) : NULL;
- new->t_type = old->t_type;
- new->t_size = old->t_size;
- new->t_id = newselfid;
- new->t_flags = old->t_flags;
-
- return (new);
-}
-
-/*ARGSUSED2*/
-static tdesc_t *
-conjure_intrinsic(tdesc_t *old, int newselfid, merge_cb_data_t *mcd)
-{
- tdesc_t *new = conjure_template(old, newselfid);
-
- new->t_intr = xmalloc(sizeof (intr_t));
- bcopy(old->t_intr, new->t_intr, sizeof (intr_t));
-
- return (new);
-}
-
-static tdesc_t *
-conjure_plain(tdesc_t *old, int newselfid, merge_cb_data_t *mcd)
-{
- tdesc_t *new = conjure_template(old, newselfid);
-
- (void) remap_node(&new->t_tdesc, old->t_tdesc, old->t_id, new, mcd);
-
- return (new);
-}
-
-static tdesc_t *
-conjure_function(tdesc_t *old, int newselfid, merge_cb_data_t *mcd)
-{
- tdesc_t *new = conjure_template(old, newselfid);
- fndef_t *nfn = xmalloc(sizeof (fndef_t));
- fndef_t *ofn = old->t_fndef;
- int i;
-
- (void) remap_node(&nfn->fn_ret, ofn->fn_ret, old->t_id, new, mcd);
-
- nfn->fn_nargs = ofn->fn_nargs;
- nfn->fn_vargs = ofn->fn_vargs;
-
- if (nfn->fn_nargs > 0)
- nfn->fn_args = xcalloc(sizeof (tdesc_t *) * ofn->fn_nargs);
-
- for (i = 0; i < ofn->fn_nargs; i++) {
- (void) remap_node(&nfn->fn_args[i], ofn->fn_args[i], old->t_id,
- new, mcd);
- }
-
- new->t_fndef = nfn;
-
- return (new);
-}
-
-static tdesc_t *
-conjure_array(tdesc_t *old, int newselfid, merge_cb_data_t *mcd)
-{
- tdesc_t *new = conjure_template(old, newselfid);
- ardef_t *nar = xmalloc(sizeof (ardef_t));
- ardef_t *oar = old->t_ardef;
-
- (void) remap_node(&nar->ad_contents, oar->ad_contents, old->t_id, new,
- mcd);
- (void) remap_node(&nar->ad_idxtype, oar->ad_idxtype, old->t_id, new,
- mcd);
-
- nar->ad_nelems = oar->ad_nelems;
-
- new->t_ardef = nar;
-
- return (new);
-}
-
-static tdesc_t *
-conjure_su(tdesc_t *old, int newselfid, merge_cb_data_t *mcd)
-{
- tdesc_t *new = conjure_template(old, newselfid);
- mlist_t *omem, **nmemp;
-
- for (omem = old->t_members, nmemp = &new->t_members;
- omem; omem = omem->ml_next, nmemp = &((*nmemp)->ml_next)) {
- *nmemp = xmalloc(sizeof (mlist_t));
- (*nmemp)->ml_offset = omem->ml_offset;
- (*nmemp)->ml_size = omem->ml_size;
- (*nmemp)->ml_name = xstrdup(omem->ml_name);
- (void) remap_node(&((*nmemp)->ml_type), omem->ml_type,
- old->t_id, new, mcd);
- }
- *nmemp = NULL;
-
- return (new);
-}
-
-/*ARGSUSED2*/
-static tdesc_t *
-conjure_enum(tdesc_t *old, int newselfid, merge_cb_data_t *mcd)
-{
- tdesc_t *new = conjure_template(old, newselfid);
- elist_t *oel, **nelp;
-
- for (oel = old->t_emem, nelp = &new->t_emem;
- oel; oel = oel->el_next, nelp = &((*nelp)->el_next)) {
- *nelp = xmalloc(sizeof (elist_t));
- (*nelp)->el_name = xstrdup(oel->el_name);
- (*nelp)->el_number = oel->el_number;
- }
- *nelp = NULL;
-
- return (new);
-}
-
-/*ARGSUSED2*/
-static tdesc_t *
-conjure_forward(tdesc_t *old, int newselfid, merge_cb_data_t *mcd)
-{
- tdesc_t *new = conjure_template(old, newselfid);
-
- list_add(&mcd->md_tgt->td_fwdlist, new);
-
- return (new);
-}
-
-/*ARGSUSED*/
-static tdesc_t *
-conjure_assert(tdesc_t *old, int newselfid, merge_cb_data_t *mcd)
-{
- assert(1 == 0);
- return (NULL);
-}
-
-static iidesc_t *
-conjure_iidesc(iidesc_t *old, merge_cb_data_t *mcd)
-{
- iidesc_t *new = iidesc_dup(old);
- int i;
-
- (void) remap_node(&new->ii_dtype, old->ii_dtype, -1, NULL, mcd);
- for (i = 0; i < new->ii_nargs; i++) {
- (void) remap_node(&new->ii_args[i], old->ii_args[i], -1, NULL,
- mcd);
- }
-
- return (new);
-}
-
-static int
-fwd_redir(tdesc_t *fwd, tdesc_t **fwdp, void *private)
-{
- alist_t *map = private;
- tdesc_t *defn;
-
- if (!alist_find(map, (void *)fwd, (void **)&defn))
- return (0);
-
- debug(3, "Redirecting an edge to %s\n", tdesc_name(defn));
-
- *fwdp = defn;
-
- return (1);
-}
-
-static tdtrav_cb_f fwd_redir_cbs[] = {
- NULL,
- NULL, /* intrinsic */
- NULL, /* pointer */
- NULL, /* array */
- NULL, /* function */
- NULL, /* struct */
- NULL, /* union */
- NULL, /* enum */
- fwd_redir, /* forward */
- NULL, /* typedef */
- tdtrav_assert, /* typedef_unres */
- NULL, /* volatile */
- NULL, /* const */
- NULL /* restrict */
-};
-
-typedef struct redir_mstr_data {
- tdata_t *rmd_tgt;
- alist_t *rmd_map;
-} redir_mstr_data_t;
-
-static int
-redir_mstr_fwd_cb(void *name, void *value, void *arg)
-{
- tdesc_t *fwd = name;
- int defnid = (int)value;
- redir_mstr_data_t *rmd = arg;
- tdesc_t template;
- tdesc_t *defn;
-
- template.t_id = defnid;
-
- if (!hash_find(rmd->rmd_tgt->td_idhash, (void *)&template,
- (void *)&defn)) {
- aborterr("Couldn't unforward %d (%s)\n", defnid,
- tdesc_name(defn));
- }
-
- debug(3, "Forward map: resolved %d to %s\n", defnid, tdesc_name(defn));
-
- alist_add(rmd->rmd_map, (void *)fwd, (void *)defn);
-
- return (1);
-}
-
-static void
-redir_mstr_fwds(merge_cb_data_t *mcd)
-{
- redir_mstr_data_t rmd;
- alist_t *map = alist_new(NULL, NULL);
-
- rmd.rmd_tgt = mcd->md_tgt;
- rmd.rmd_map = map;
-
- if (alist_iter(mcd->md_fdida, redir_mstr_fwd_cb, &rmd)) {
- (void) iitraverse_hash(mcd->md_tgt->td_iihash,
- &mcd->md_tgt->td_curvgen, fwd_redir_cbs, NULL, NULL, map);
- }
-
- alist_free(map);
-}
-
-static int
-add_iitba_cb(void *data, void *private)
-{
- merge_cb_data_t *mcd = private;
- iidesc_t *tba = data;
- iidesc_t *new;
- iifind_data_t iif;
- int newidx;
-
- newidx = get_mapping(mcd->md_ta, tba->ii_dtype->t_id);
- assert(newidx != -1);
-
- (void) list_remove(mcd->md_iitba, data, NULL, NULL);
-
- iif.iif_template = tba;
- iif.iif_ta = mcd->md_ta;
- iif.iif_newidx = newidx;
- iif.iif_refmerge = (mcd->md_flags & MCD_F_REFMERGE);
-
- if (hash_match(mcd->md_parent->td_iihash, tba, iidesc_match,
- &iif) == 1) {
- debug(3, "iidesc_t %s already exists\n",
- (tba->ii_name ? tba->ii_name : "(anon)"));
- return (1);
- }
-
- new = conjure_iidesc(tba, mcd);
- hash_add(mcd->md_tgt->td_iihash, new);
-
- return (1);
-}
-
-static int
-add_tdesc(tdesc_t *oldtdp, int newid, merge_cb_data_t *mcd)
-{
- tdesc_t *newtdp;
- tdesc_t template;
-
- template.t_id = newid;
- assert(hash_find(mcd->md_parent->td_idhash,
- (void *)&template, NULL) == 0);
-
- debug(3, "trying to conjure %d %s (%d) as %d\n",
- oldtdp->t_type, tdesc_name(oldtdp), oldtdp->t_id, newid);
-
- if ((newtdp = tdesc_ops[oldtdp->t_type].conjure(oldtdp, newid,
- mcd)) == NULL)
- /* couldn't map everything */
- return (0);
-
- debug(3, "succeeded\n");
-
- hash_add(mcd->md_tgt->td_idhash, newtdp);
- hash_add(mcd->md_tgt->td_layouthash, newtdp);
-
- return (1);
-}
-
-static int
-add_tdtba_cb(void *data, void *arg)
-{
- tdesc_t *tdp = data;
- merge_cb_data_t *mcd = arg;
- int newid;
- int rc;
-
- newid = get_mapping(mcd->md_ta, tdp->t_id);
- assert(newid != -1);
-
- if ((rc = add_tdesc(tdp, newid, mcd)))
- hash_remove(mcd->md_tdtba, (void *)tdp);
-
- return (rc);
-}
-
-static int
-add_tdtbr_cb(void *data, void *arg)
-{
- tdesc_t **tdpp = data;
- merge_cb_data_t *mcd = arg;
-
- debug(3, "Remapping %s (%d)\n", tdesc_name(*tdpp), (*tdpp)->t_id);
-
- if (!remap_node(tdpp, *tdpp, -1, NULL, mcd))
- return (0);
-
- (void) list_remove(mcd->md_tdtbr, (void *)tdpp, NULL, NULL);
- return (1);
-}
-
-static void
-merge_types(hash_t *src, merge_cb_data_t *mcd)
-{
- list_t *iitba = NULL;
- list_t *tdtbr = NULL;
- int iirc, tdrc;
-
- mcd->md_iitba = &iitba;
- mcd->md_tdtba = hash_new(TDATA_LAYOUT_HASH_SIZE, tdesc_layouthash,
- tdesc_layoutcmp);
- mcd->md_tdtbr = &tdtbr;
-
- (void) hash_iter(src, merge_type_cb, mcd);
-
- tdrc = hash_iter(mcd->md_tdtba, add_tdtba_cb, (void *)mcd);
- debug(3, "add_tdtba_cb added %d items\n", tdrc);
-
- iirc = list_iter(*mcd->md_iitba, add_iitba_cb, (void *)mcd);
- debug(3, "add_iitba_cb added %d items\n", iirc);
-
- assert(list_count(*mcd->md_iitba) == 0 &&
- hash_count(mcd->md_tdtba) == 0);
-
- tdrc = list_iter(*mcd->md_tdtbr, add_tdtbr_cb, (void *)mcd);
- debug(3, "add_tdtbr_cb added %d items\n", tdrc);
-
- if (list_count(*mcd->md_tdtbr) != 0)
- aborterr("Couldn't remap all nodes\n");
-
- /*
- * We now have an alist of master forwards and the ids of the new master
- * definitions for those forwards in mcd->md_fdida. By this point,
- * we're guaranteed that all of the master definitions referenced in
- * fdida have been added to the master tree. We now traverse through
- * the master tree, redirecting all edges inbound to forwards that have
- * definitions to those definitions.
- */
- if (mcd->md_parent == mcd->md_tgt) {
- redir_mstr_fwds(mcd);
- }
-}
-
-void
-merge_into_master(tdata_t *cur, tdata_t *mstr, tdata_t *tgt, int selfuniquify)
-{
- merge_cb_data_t mcd;
-
- cur->td_ref++;
- mstr->td_ref++;
- if (tgt)
- tgt->td_ref++;
-
- assert(cur->td_ref == 1 && mstr->td_ref == 1 &&
- (tgt == NULL || tgt->td_ref == 1));
-
- mcd.md_parent = mstr;
- mcd.md_tgt = (tgt ? tgt : mstr);
- mcd.md_ta = alist_new(NULL, NULL);
- mcd.md_fdida = alist_new(NULL, NULL);
- mcd.md_flags = 0;
-
- if (selfuniquify)
- mcd.md_flags |= MCD_F_SELFUNIQUIFY;
- if (tgt)
- mcd.md_flags |= MCD_F_REFMERGE;
-
- mstr->td_curvgen = MAX(mstr->td_curvgen, cur->td_curvgen);
- mstr->td_curemark = MAX(mstr->td_curemark, cur->td_curemark);
-
- merge_types(cur->td_iihash, &mcd);
-
- if (debug_level >= 3) {
- debug(3, "Type association stats\n");
- alist_stats(mcd.md_ta, 0);
- debug(3, "Layout hash stats\n");
- hash_stats(mcd.md_tgt->td_layouthash, 1);
- }
-
- alist_free(mcd.md_fdida);
- alist_free(mcd.md_ta);
-
- cur->td_ref--;
- mstr->td_ref--;
- if (tgt)
- tgt->td_ref--;
-}
-
-tdesc_ops_t tdesc_ops[] = {
- { "ERROR! BAD tdesc TYPE", NULL, NULL },
- { "intrinsic", equiv_intrinsic, conjure_intrinsic },
- { "pointer", equiv_plain, conjure_plain },
- { "array", equiv_array, conjure_array },
- { "function", equiv_function, conjure_function },
- { "struct", equiv_su, conjure_su },
- { "union", equiv_su, conjure_su },
- { "enum", equiv_enum, conjure_enum },
- { "forward", NULL, conjure_forward },
- { "typedef", equiv_plain, conjure_plain },
- { "typedef_unres", equiv_assert, conjure_assert },
- { "volatile", equiv_plain, conjure_plain },
- { "const", equiv_plain, conjure_plain },
- { "restrict", equiv_plain, conjure_plain }
-};
diff --git a/usr/src/tools/ctf/cvt/output.c b/usr/src/tools/ctf/cvt/output.c
deleted file mode 100644
index f23aa7394c..0000000000
--- a/usr/src/tools/ctf/cvt/output.c
+++ /dev/null
@@ -1,713 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * Routines for preparing tdata trees for conversion into CTF data, and
- * for placing the resulting data into an output file.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <libelf.h>
-#include <gelf.h>
-#include <unistd.h>
-
-#include "ctftools.h"
-#include "list.h"
-#include "memory.h"
-#include "traverse.h"
-#include "symbol.h"
-
-typedef struct iidesc_match {
- int iim_fuzzy;
- iidesc_t *iim_ret;
- char *iim_name;
- char *iim_file;
- uchar_t iim_bind;
-} iidesc_match_t;
-
-static int
-burst_iitypes(void *data, void *arg)
-{
- iidesc_t *ii = data;
- iiburst_t *iiburst = arg;
-
- switch (ii->ii_type) {
- case II_GFUN:
- case II_SFUN:
- case II_GVAR:
- case II_SVAR:
- if (!(ii->ii_flags & IIDESC_F_USED))
- return (0);
- break;
- default:
- break;
- }
-
- ii->ii_dtype->t_flags |= TDESC_F_ISROOT;
- (void) iitraverse_td(ii, iiburst->iib_tdtd);
- return (1);
-}
-
-/*ARGSUSED1*/
-static int
-save_type_by_id(tdesc_t *tdp, tdesc_t **tdpp, void *private)
-{
- iiburst_t *iiburst = private;
-
- /*
- * Doing this on every node is horribly inefficient, but given that
- * we may be suppressing some types, we can't trust nextid in the
- * tdata_t.
- */
- if (tdp->t_id > iiburst->iib_maxtypeid)
- iiburst->iib_maxtypeid = tdp->t_id;
-
- slist_add(&iiburst->iib_types, tdp, tdesc_idcmp);
-
- return (1);
-}
-
-static tdtrav_cb_f burst_types_cbs[] = {
- NULL,
- save_type_by_id, /* intrinsic */
- save_type_by_id, /* pointer */
- save_type_by_id, /* array */
- save_type_by_id, /* function */
- save_type_by_id, /* struct */
- save_type_by_id, /* union */
- save_type_by_id, /* enum */
- save_type_by_id, /* forward */
- save_type_by_id, /* typedef */
- tdtrav_assert, /* typedef_unres */
- save_type_by_id, /* volatile */
- save_type_by_id, /* const */
- save_type_by_id /* restrict */
-};
-
-
-static iiburst_t *
-iiburst_new(tdata_t *td, int max)
-{
- iiburst_t *iiburst = xcalloc(sizeof (iiburst_t));
- iiburst->iib_td = td;
- iiburst->iib_funcs = xcalloc(sizeof (iidesc_t *) * max);
- iiburst->iib_nfuncs = 0;
- iiburst->iib_objts = xcalloc(sizeof (iidesc_t *) * max);
- iiburst->iib_nobjts = 0;
- return (iiburst);
-}
-
-static void
-iiburst_types(iiburst_t *iiburst)
-{
- tdtrav_data_t tdtd;
-
- tdtrav_init(&tdtd, &iiburst->iib_td->td_curvgen, NULL, burst_types_cbs,
- NULL, (void *)iiburst);
-
- iiburst->iib_tdtd = &tdtd;
-
- (void) hash_iter(iiburst->iib_td->td_iihash, burst_iitypes, iiburst);
-}
-
-static void
-iiburst_free(iiburst_t *iiburst)
-{
- free(iiburst->iib_funcs);
- free(iiburst->iib_objts);
- list_free(iiburst->iib_types, NULL, NULL);
- free(iiburst);
-}
-
-/*
- * See if this iidesc matches the ELF symbol data we pass in.
- *
- * A fuzzy match is where we have a local symbol matching the name of a
- * global type description. This is common when a mapfile is used for a
- * DSO, but we don't accept it by default.
- *
- * A weak fuzzy match is when a weak symbol was resolved and matched to
- * a global type description.
- */
-static int
-matching_iidesc(iidesc_t *iidesc, iidesc_match_t *match)
-{
- if (streq(iidesc->ii_name, match->iim_name) == 0)
- return (0);
-
- switch (iidesc->ii_type) {
- case II_GFUN:
- case II_GVAR:
- if (match->iim_bind == STB_GLOBAL) {
- match->iim_ret = iidesc;
- return (-1);
- } else if (match->iim_fuzzy && match->iim_ret == NULL) {
- match->iim_ret = iidesc;
- /* continue to look for strong match */
- return (0);
- }
- break;
- case II_SFUN:
- case II_SVAR:
- if (match->iim_bind == STB_LOCAL &&
- match->iim_file != NULL &&
- streq(iidesc->ii_owner, match->iim_file)) {
- match->iim_ret = iidesc;
- return (-1);
- }
- break;
- }
- return (0);
-}
-
-static iidesc_t *
-find_iidesc(tdata_t *td, iidesc_match_t *match)
-{
- match->iim_ret = NULL;
- iter_iidescs_by_name(td, match->iim_name,
- (int (*)())matching_iidesc, match);
- return (match->iim_ret);
-}
-
-/*
- * If we have a weak symbol, attempt to find the strong symbol it will
- * resolve to. Note: the code where this actually happens is in
- * sym_process() in cmd/sgs/libld/common/syms.c
- *
- * Finding the matching symbol is unfortunately not trivial. For a
- * symbol to be a candidate, it must:
- *
- * - have the same type (function, object)
- * - have the same value (address)
- * - have the same size
- * - not be another weak symbol
- * - belong to the same section (checked via section index)
- *
- * If such a candidate is global, then we assume we've found it. The
- * linker generates the symbol table such that the curfile might be
- * incorrect; this is OK for global symbols, since find_iidesc() doesn't
- * need to check for the source file for the symbol.
- *
- * We might have found a strong local symbol, where the curfile is
- * accurate and matches that of the weak symbol. We assume this is a
- * reasonable match.
- *
- * If we've got a local symbol with a non-matching curfile, there are
- * two possibilities. Either this is a completely different symbol, or
- * it's a once-global symbol that was scoped to local via a mapfile. In
- * the latter case, curfile is likely inaccurate since the linker does
- * not preserve the needed curfile in the order of the symbol table (see
- * the comments about locally scoped symbols in libld's update_osym()).
- * As we can't tell this case from the former one, we use this symbol
- * iff no other matching symbol is found.
- *
- * What we really need here is a SUNW section containing weak<->strong
- * mappings that we can consume.
- */
-static int
-check_for_weak(GElf_Sym *weak, char const *weakfile,
- Elf_Data *data, int nent, Elf_Data *strdata,
- GElf_Sym *retsym, char **curfilep)
-{
- char *curfile = NULL;
- char *tmpfile;
- GElf_Sym tmpsym;
- int candidate = 0;
- int i;
-
- if (GELF_ST_BIND(weak->st_info) != STB_WEAK)
- return (0);
-
- for (i = 0; i < nent; i++) {
- GElf_Sym sym;
- uchar_t type;
-
- if (gelf_getsym(data, i, &sym) == NULL)
- continue;
-
- type = GELF_ST_TYPE(sym.st_info);
-
- if (type == STT_FILE)
- curfile = (char *)strdata->d_buf + sym.st_name;
-
- if (GELF_ST_TYPE(weak->st_info) != type ||
- weak->st_value != sym.st_value)
- continue;
-
- if (weak->st_size != sym.st_size)
- continue;
-
- if (GELF_ST_BIND(sym.st_info) == STB_WEAK)
- continue;
-
- if (sym.st_shndx != weak->st_shndx)
- continue;
-
- if (GELF_ST_BIND(sym.st_info) == STB_LOCAL &&
- (curfile == NULL || weakfile == NULL ||
- strcmp(curfile, weakfile) != 0)) {
- candidate = 1;
- tmpfile = curfile;
- tmpsym = sym;
- continue;
- }
-
- *curfilep = curfile;
- *retsym = sym;
- return (1);
- }
-
- if (candidate) {
- *curfilep = tmpfile;
- *retsym = tmpsym;
- return (1);
- }
-
- return (0);
-}
-
-/*
- * When we've found the underlying symbol's type description
- * for a weak symbol, we need to copy it and rename it to match
- * the weak symbol. We also need to add it to the td so it's
- * handled along with the others later.
- */
-static iidesc_t *
-copy_from_strong(tdata_t *td, GElf_Sym *sym, iidesc_t *strongdesc,
- const char *weakname, const char *weakfile)
-{
- iidesc_t *new = iidesc_dup_rename(strongdesc, weakname, weakfile);
- uchar_t type = GELF_ST_TYPE(sym->st_info);
-
- switch (type) {
- case STT_OBJECT:
- new->ii_type = II_GVAR;
- break;
- case STT_FUNC:
- new->ii_type = II_GFUN;
- break;
- }
-
- hash_add(td->td_iihash, new);
-
- return (new);
-}
-
-/*
- * Process the symbol table of the output file, associating each symbol
- * with a type description if possible, and sorting them into functions
- * and data, maintaining symbol table order.
- */
-static iiburst_t *
-sort_iidescs(Elf *elf, const char *file, tdata_t *td, int fuzzymatch,
- int dynsym)
-{
- iiburst_t *iiburst;
- Elf_Scn *scn;
- GElf_Shdr shdr;
- Elf_Data *data, *strdata;
- int i, stidx;
- int nent;
- iidesc_match_t match;
-
- match.iim_fuzzy = fuzzymatch;
- match.iim_file = NULL;
-
- if ((stidx = findelfsecidx(elf, file,
- dynsym ? ".dynsym" : ".symtab")) < 0)
- terminate("%s: Can't open symbol table\n", file);
- scn = elf_getscn(elf, stidx);
- data = elf_getdata(scn, NULL);
- gelf_getshdr(scn, &shdr);
- nent = shdr.sh_size / shdr.sh_entsize;
-
- scn = elf_getscn(elf, shdr.sh_link);
- strdata = elf_getdata(scn, NULL);
-
- iiburst = iiburst_new(td, nent);
-
- for (i = 0; i < nent; i++) {
- GElf_Sym sym;
- iidesc_t **tolist;
- GElf_Sym ssym;
- iidesc_match_t smatch;
- int *curr;
- iidesc_t *iidesc;
-
- if (gelf_getsym(data, i, &sym) == NULL)
- elfterminate(file, "Couldn't read symbol %d", i);
-
- match.iim_name = (char *)strdata->d_buf + sym.st_name;
- match.iim_bind = GELF_ST_BIND(sym.st_info);
-
- switch (GELF_ST_TYPE(sym.st_info)) {
- case STT_FILE:
- match.iim_file = match.iim_name;
- continue;
- case STT_OBJECT:
- tolist = iiburst->iib_objts;
- curr = &iiburst->iib_nobjts;
- break;
- case STT_FUNC:
- tolist = iiburst->iib_funcs;
- curr = &iiburst->iib_nfuncs;
- break;
- default:
- continue;
- }
-
- if (ignore_symbol(&sym, match.iim_name))
- continue;
-
- iidesc = find_iidesc(td, &match);
-
- if (iidesc != NULL) {
- tolist[*curr] = iidesc;
- iidesc->ii_flags |= IIDESC_F_USED;
- (*curr)++;
- continue;
- }
-
- if (!check_for_weak(&sym, match.iim_file, data, nent, strdata,
- &ssym, &smatch.iim_file)) {
- (*curr)++;
- continue;
- }
-
- smatch.iim_fuzzy = fuzzymatch;
- smatch.iim_name = (char *)strdata->d_buf + ssym.st_name;
- smatch.iim_bind = GELF_ST_BIND(ssym.st_info);
-
- debug(3, "Weak symbol %s resolved to %s\n", match.iim_name,
- smatch.iim_name);
-
- iidesc = find_iidesc(td, &smatch);
-
- if (iidesc != NULL) {
- tolist[*curr] = copy_from_strong(td, &sym,
- iidesc, match.iim_name, match.iim_file);
- tolist[*curr]->ii_flags |= IIDESC_F_USED;
- }
-
- (*curr)++;
- }
-
- /*
- * Stabs are generated for every function declared in a given C source
- * file. When converting an object file, we may encounter a stab that
- * has no symbol table entry because the optimizer has decided to omit
- * that item (for example, an unreferenced static function). We may
- * see iidescs that do not have an associated symtab entry, and so
- * we do not write records for those functions into the CTF data.
- * All others get marked as a root by this function.
- */
- iiburst_types(iiburst);
-
- /*
- * By not adding some of the functions and/or objects, we may have
- * caused some types that were referenced solely by those
- * functions/objects to be suppressed. This could cause a label,
- * generated prior to the evisceration, to be incorrect. Find the
- * highest type index, and change the label indicies to be no higher
- * than this value.
- */
- tdata_label_newmax(td, iiburst->iib_maxtypeid);
-
- return (iiburst);
-}
-
-static void
-write_file(Elf *src, const char *srcname, Elf *dst, const char *dstname,
- caddr_t ctfdata, size_t ctfsize, int flags)
-{
- GElf_Ehdr sehdr, dehdr;
- Elf_Scn *sscn, *dscn;
- Elf_Data *sdata, *ddata;
- GElf_Shdr shdr;
- GElf_Word symtab_type;
- int symtab_idx = -1;
- off_t new_offset = 0;
- off_t ctfnameoff = 0;
- int dynsym = (flags & CTF_USE_DYNSYM);
- int *secxlate;
- int srcidx, dstidx;
- int curnmoff = 0;
- int changing = 0;
- int pad;
- int i;
-
- if (gelf_newehdr(dst, gelf_getclass(src)) == 0)
- elfterminate(dstname, "Cannot copy ehdr to temp file");
- gelf_getehdr(src, &sehdr);
- memcpy(&dehdr, &sehdr, sizeof (GElf_Ehdr));
- gelf_update_ehdr(dst, &dehdr);
-
- symtab_type = dynsym ? SHT_DYNSYM : SHT_SYMTAB;
-
- /*
- * Neither the existing stab sections nor the SUNW_ctf sections (new or
- * existing) are SHF_ALLOC'd, so they won't be in areas referenced by
- * program headers. As such, we can just blindly copy the program
- * headers from the existing file to the new file.
- */
- if (sehdr.e_phnum != 0) {
- (void) elf_flagelf(dst, ELF_C_SET, ELF_F_LAYOUT);
- if (gelf_newphdr(dst, sehdr.e_phnum) == 0)
- elfterminate(dstname, "Cannot make phdrs in temp file");
-
- for (i = 0; i < sehdr.e_phnum; i++) {
- GElf_Phdr phdr;
-
- gelf_getphdr(src, i, &phdr);
- gelf_update_phdr(dst, i, &phdr);
- }
- }
-
- secxlate = xmalloc(sizeof (int) * sehdr.e_shnum);
- for (srcidx = dstidx = 0; srcidx < sehdr.e_shnum; srcidx++) {
- Elf_Scn *scn = elf_getscn(src, srcidx);
- GElf_Shdr shdr;
- char *sname;
-
- gelf_getshdr(scn, &shdr);
- sname = elf_strptr(src, sehdr.e_shstrndx, shdr.sh_name);
- if (sname == NULL) {
- elfterminate(srcname, "Can't find string at %u",
- shdr.sh_name);
- }
-
- if (strcmp(sname, CTF_ELF_SCN_NAME) == 0) {
- secxlate[srcidx] = -1;
- } else if (dynsym && shdr.sh_type == SHT_SYMTAB) {
- /*
- * If we're building CTF against the dynsym,
- * we'll rip out the symtab so debuggers aren't
- * confused.
- */
- secxlate[srcidx] = -1;
- } else {
- secxlate[srcidx] = dstidx++;
- curnmoff += strlen(sname) + 1;
- }
-
- new_offset = (off_t)dehdr.e_phoff;
- }
-
- for (srcidx = 1; srcidx < sehdr.e_shnum; srcidx++) {
- char *sname;
-
- sscn = elf_getscn(src, srcidx);
- gelf_getshdr(sscn, &shdr);
-
- if (secxlate[srcidx] == -1) {
- changing = 1;
- continue;
- }
-
- dscn = elf_newscn(dst);
-
- /*
- * If this file has program headers, we need to explicitly lay
- * out sections. If none of the sections prior to this one have
- * been removed, then we can just use the existing location. If
- * one or more sections have been changed, then we need to
- * adjust this one to avoid holes.
- */
- if (changing && sehdr.e_phnum != 0) {
- pad = new_offset % shdr.sh_addralign;
-
- if (pad)
- new_offset += shdr.sh_addralign - pad;
- shdr.sh_offset = new_offset;
- }
-
- shdr.sh_link = secxlate[shdr.sh_link];
-
- if (shdr.sh_type == SHT_REL || shdr.sh_type == SHT_RELA)
- shdr.sh_info = secxlate[shdr.sh_info];
-
- sname = elf_strptr(src, sehdr.e_shstrndx, shdr.sh_name);
- if (sname == NULL) {
- elfterminate(srcname, "Can't find string at %u",
- shdr.sh_name);
- }
- if ((sdata = elf_getdata(sscn, NULL)) == NULL)
- elfterminate(srcname, "Cannot get sect %s data", sname);
- if ((ddata = elf_newdata(dscn)) == NULL)
- elfterminate(dstname, "Can't make sect %s data", sname);
- bcopy(sdata, ddata, sizeof (Elf_Data));
-
- if (srcidx == sehdr.e_shstrndx) {
- char seclen = strlen(CTF_ELF_SCN_NAME);
-
- ddata->d_buf = xmalloc(ddata->d_size + shdr.sh_size +
- seclen + 1);
- bcopy(sdata->d_buf, ddata->d_buf, shdr.sh_size);
- strcpy((caddr_t)ddata->d_buf + shdr.sh_size,
- CTF_ELF_SCN_NAME);
- ctfnameoff = (off_t)shdr.sh_size;
- shdr.sh_size += seclen + 1;
- ddata->d_size += seclen + 1;
-
- if (sehdr.e_phnum != 0)
- changing = 1;
- }
-
- if (shdr.sh_type == symtab_type && shdr.sh_entsize != 0) {
- int nsym = shdr.sh_size / shdr.sh_entsize;
-
- symtab_idx = secxlate[srcidx];
-
- ddata->d_buf = xmalloc(shdr.sh_size);
- bcopy(sdata->d_buf, ddata->d_buf, shdr.sh_size);
-
- for (i = 0; i < nsym; i++) {
- GElf_Sym sym;
- short newscn;
-
- (void) gelf_getsym(ddata, i, &sym);
-
- if (sym.st_shndx >= SHN_LORESERVE)
- continue;
-
- if ((newscn = secxlate[sym.st_shndx]) !=
- sym.st_shndx) {
- sym.st_shndx =
- (newscn == -1 ? 1 : newscn);
-
- gelf_update_sym(ddata, i, &sym);
- }
- }
- }
-
- if (gelf_update_shdr(dscn, &shdr) == 0)
- elfterminate(dstname, "Cannot update sect %s", sname);
-
- new_offset = (off_t)shdr.sh_offset;
- if (shdr.sh_type != SHT_NOBITS)
- new_offset += shdr.sh_size;
- }
-
- if (symtab_idx == -1) {
- terminate("%s: Cannot find %s section\n", srcname,
- dynsym ? "SHT_DYNSYM" : "SHT_SYMTAB");
- }
-
- /* Add the ctf section */
- dscn = elf_newscn(dst);
- gelf_getshdr(dscn, &shdr);
- shdr.sh_name = ctfnameoff;
- shdr.sh_type = SHT_PROGBITS;
- shdr.sh_size = ctfsize;
- shdr.sh_link = symtab_idx;
- shdr.sh_addralign = 4;
- if (changing && sehdr.e_phnum != 0) {
- pad = new_offset % shdr.sh_addralign;
-
- if (pad)
- new_offset += shdr.sh_addralign - pad;
-
- shdr.sh_offset = new_offset;
- new_offset += shdr.sh_size;
- }
-
- ddata = elf_newdata(dscn);
- ddata->d_buf = ctfdata;
- ddata->d_size = ctfsize;
- ddata->d_align = shdr.sh_addralign;
-
- gelf_update_shdr(dscn, &shdr);
-
- /* update the section header location */
- if (sehdr.e_phnum != 0) {
- size_t align = gelf_fsize(dst, ELF_T_ADDR, 1, EV_CURRENT);
- size_t r = new_offset % align;
-
- if (r)
- new_offset += align - r;
-
- dehdr.e_shoff = new_offset;
- }
-
- /* commit to disk */
- dehdr.e_shstrndx = secxlate[sehdr.e_shstrndx];
- gelf_update_ehdr(dst, &dehdr);
- if (elf_update(dst, ELF_C_WRITE) < 0)
- elfterminate(dstname, "Cannot finalize temp file");
-
- free(secxlate);
-}
-
-static caddr_t
-make_ctf_data(tdata_t *td, Elf *elf, const char *file, size_t *lenp, int flags)
-{
- iiburst_t *iiburst;
- caddr_t data;
-
- iiburst = sort_iidescs(elf, file, td, flags & CTF_FUZZY_MATCH,
- flags & CTF_USE_DYNSYM);
- data = ctf_gen(iiburst, lenp, flags & CTF_COMPRESS);
-
- iiburst_free(iiburst);
-
- return (data);
-}
-
-void
-write_ctf(tdata_t *td, const char *curname, const char *newname, int flags)
-{
- struct stat st;
- Elf *elf = NULL;
- Elf *telf = NULL;
- caddr_t data;
- size_t len;
- int fd = -1;
- int tfd = -1;
-
- (void) elf_version(EV_CURRENT);
- if ((fd = open(curname, O_RDONLY)) < 0 || fstat(fd, &st) < 0)
- terminate("%s: Cannot open for re-reading", curname);
- if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL)
- elfterminate(curname, "Cannot re-read");
-
- if ((tfd = open(newname, O_RDWR | O_CREAT | O_TRUNC, st.st_mode)) < 0)
- terminate("Cannot open temp file %s for writing", newname);
- if ((telf = elf_begin(tfd, ELF_C_WRITE, NULL)) == NULL)
- elfterminate(curname, "Cannot write");
-
- data = make_ctf_data(td, elf, curname, &len, flags);
- write_file(elf, curname, telf, newname, data, len, flags);
- free(data);
-
- elf_end(telf);
- elf_end(elf);
- (void) close(fd);
- (void) close(tfd);
-}
diff --git a/usr/src/tools/ctf/cvt/sparc/Makefile b/usr/src/tools/ctf/cvt/sparc/Makefile
deleted file mode 100644
index 999f6c9af8..0000000000
--- a/usr/src/tools/ctf/cvt/sparc/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# 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 2001-2003 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-#ident "%Z%%M% %I% %E% SMI"
-
-include ../Makefile.com
-include ../Makefile.targ
diff --git a/usr/src/tools/ctf/cvt/st_parse.c b/usr/src/tools/ctf/cvt/st_parse.c
deleted file mode 100644
index 37e7756cdf..0000000000
--- a/usr/src/tools/ctf/cvt/st_parse.c
+++ /dev/null
@@ -1,1214 +0,0 @@
-/*
- * 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 (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-/*
- * Copyright (c) 2018, Joyent, Inc.
- */
-
-/*
- * This file is a sewer.
- */
-
-#include <limits.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <assert.h>
-#include <strings.h>
-#include <setjmp.h>
-#include <ctype.h>
-#include <uts/common/sys/ctf.h>
-
-#include "ctftools.h"
-#include "memory.h"
-#include "list.h"
-
-#define HASH(NUM) ((int)(NUM & (BUCKETS - 1)))
-#define BUCKETS 128
-
-#define TYPEPAIRMULT 10000
-#define MAKETYPEID(file, num) ((file) * TYPEPAIRMULT + num)
-#define TYPEFILE(tid) ((tid) / TYPEPAIRMULT)
-#define TYPENUM(tid) ((tid) % TYPEPAIRMULT)
-
-#define expected(a, b, c) _expected(a, b, c, __LINE__)
-
-static int faketypenumber = 100000000;
-
-static tdesc_t *hash_table[BUCKETS];
-static tdesc_t *name_table[BUCKETS];
-
-list_t *typedbitfldmems;
-
-static void reset(void);
-static jmp_buf resetbuf;
-
-static char *soudef(char *cp, stabtype_t type, tdesc_t **rtdp);
-static void enumdef(char *cp, tdesc_t **rtdp);
-static int compute_sum(const char *w);
-
-static char *number(char *cp, int *n);
-static char *name(char *cp, char **w);
-static char *id(char *cp, int *h);
-static char *whitesp(char *cp);
-static void addhash(tdesc_t *tdp, int num);
-static int tagadd(char *w, int h, tdesc_t *tdp);
-static char *tdefdecl(char *cp, int h, tdesc_t **rtdp);
-static char *intrinsic(char *cp, tdesc_t **rtdp);
-static char *arraydef(char *cp, tdesc_t **rtdp);
-
-extern int debug_level;
-int debug_parse = DEBUG_PARSE;
-
-/*PRINTFLIKE3*/
-static void
-parse_debug(int level, char *cp, char *fmt, ...)
-{
- va_list ap;
- char buf[1024];
- char tmp[32];
- int i;
-
- if (level > debug_level || !debug_parse)
- return;
-
- if (cp != NULL) {
- for (i = 0; i < 30; i++) {
- if (cp[i] == '\0')
- break;
- if (!iscntrl(cp[i]))
- tmp[i] = cp[i];
- }
- tmp[i] = '\0';
- (void) snprintf(buf, sizeof (buf), "%s [cp='%s']\n", fmt, tmp);
- } else {
- strcpy(buf, fmt);
- strcat(buf, "\n");
- }
-
- va_start(ap, fmt);
- vadebug(level, buf, ap);
- va_end(ap);
-}
-
-/* Report unexpected syntax in stabs. */
-static void
-_expected(
- char *who, /* what function, or part thereof, is reporting */
- char *what, /* what was expected */
- char *where, /* where we were in the line of input */
- int line)
-{
- fprintf(stderr, "%s, expecting \"%s\" at \"%s\"\n", who, what, where);
- fprintf(stderr, "code line: %d, file %s\n", line,
- (curhdr ? curhdr : "NO FILE"));
- reset();
-}
-
-/*ARGSUSED*/
-void
-parse_init(tdata_t *td)
-{
- int i;
-
- for (i = 0; i < BUCKETS; i++) {
- hash_table[i] = NULL;
- name_table[i] = NULL;
- }
-
- if (typedbitfldmems != NULL) {
- list_free(typedbitfldmems, NULL, NULL);
- typedbitfldmems = NULL;
- }
-}
-
-void
-parse_finish(tdata_t *td)
-{
- td->td_nextid = ++faketypenumber;
-}
-
-static tdesc_t *
-unres_new(int tid)
-{
- tdesc_t *tdp;
-
- tdp = xcalloc(sizeof (*tdp));
- tdp->t_type = TYPEDEF_UNRES;
- tdp->t_id = tid;
-
- return (tdp);
-}
-
-char *
-read_tid(char *cp, tdesc_t **tdpp)
-{
- tdesc_t *tdp;
- int tid;
-
- cp = id(cp, &tid);
-
- assert(tid != 0);
-
- if (*cp == '=') {
- if (!(cp = tdefdecl(cp + 1, tid, &tdp)))
- return (NULL);
- if (tdp->t_id && tdp->t_id != tid) {
- tdesc_t *ntdp = xcalloc(sizeof (*ntdp));
-
- ntdp->t_type = TYPEDEF;
- ntdp->t_tdesc = tdp;
- tdp = ntdp;
- }
- addhash(tdp, tid);
- } else if ((tdp = lookup(tid)) == NULL)
- tdp = unres_new(tid);
-
- *tdpp = tdp;
- return (cp);
-}
-
-static iitype_t
-parse_fun(char *cp, iidesc_t *ii)
-{
- iitype_t iitype;
- tdesc_t *tdp;
- tdesc_t **args = NULL;
- int nargs = 0;
- int va = 0;
-
- /*
- * name:P prototype
- * name:F global function
- * name:f static function
- */
- switch (*cp++) {
- case 'P':
- iitype = II_NOT; /* not interesting */
- break;
-
- case 'F':
- iitype = II_GFUN;
- break;
-
- case 'f':
- iitype = II_SFUN;
- break;
-
- default:
- expected("parse_nfun", "[PfF]", cp - 1);
- }
-
- if (!(cp = read_tid(cp, &tdp)))
- return (-1);
-
- if (*cp)
- args = xmalloc(sizeof (tdesc_t *) * FUNCARG_DEF);
-
- while (*cp && *++cp) {
- if (*cp == '0') {
- va = 1;
- continue;
- }
-
- nargs++;
- if (nargs > FUNCARG_DEF)
- args = xrealloc(args, sizeof (tdesc_t *) * nargs);
- if (!(cp = read_tid(cp, &args[nargs - 1])))
- return (-1);
- }
-
- ii->ii_type = iitype;
- ii->ii_dtype = tdp;
- ii->ii_nargs = nargs;
- ii->ii_args = args;
- ii->ii_vargs = va;
-
- return (iitype);
-}
-
-static iitype_t
-parse_sym(char *cp, iidesc_t *ii)
-{
- tdesc_t *tdp;
- iitype_t iitype;
-
- /*
- * name:G global variable
- * name:S static variable
- */
- switch (*cp++) {
- case 'G':
- iitype = II_GVAR;
- break;
- case 'S':
- iitype = II_SVAR;
- break;
- case 'p':
- iitype = II_PSYM;
- break;
- case '(':
- cp--;
- /*FALLTHROUGH*/
- case 'r':
- case 'V':
- iitype = II_NOT; /* not interesting */
- break;
- default:
- expected("parse_sym", "[GprSV(]", cp - 1);
- }
-
- if (!(cp = read_tid(cp, &tdp)))
- return (-1);
-
- ii->ii_type = iitype;
- ii->ii_dtype = tdp;
-
- return (iitype);
-}
-
-static iitype_t
-parse_type(char *cp, iidesc_t *ii)
-{
- tdesc_t *tdp, *ntdp;
- int tid;
-
- if (*cp++ != 't')
- expected("parse_type", "t (type)", cp - 1);
-
- cp = id(cp, &tid);
- if ((tdp = lookup(tid)) == NULL) {
- if (*cp++ != '=')
- expected("parse_type", "= (definition)", cp - 1);
-
- (void) tdefdecl(cp, tid, &tdp);
-
- if (tdp->t_id == tid) {
- assert(tdp->t_type != TYPEDEF);
- assert(!lookup(tdp->t_id));
-
- if (!streq(tdp->t_name, ii->ii_name)) {
- ntdp = xcalloc(sizeof (*ntdp));
- ntdp->t_name = xstrdup(ii->ii_name);
- ntdp->t_type = TYPEDEF;
- ntdp->t_tdesc = tdp;
- tdp->t_id = faketypenumber++;
- tdp = ntdp;
- }
- } else if (tdp->t_id == 0) {
- assert(tdp->t_type == FORWARD ||
- tdp->t_type == INTRINSIC);
-
- if (tdp->t_name && !streq(tdp->t_name, ii->ii_name)) {
- ntdp = xcalloc(sizeof (*ntdp));
- ntdp->t_name = xstrdup(ii->ii_name);
- ntdp->t_type = TYPEDEF;
- ntdp->t_tdesc = tdp;
- tdp->t_id = faketypenumber++;
- tdp = ntdp;
- }
- } else if (tdp->t_id != tid) {
- ntdp = xcalloc(sizeof (*ntdp));
- ntdp->t_name = xstrdup(ii->ii_name);
- ntdp->t_type = TYPEDEF;
- ntdp->t_tdesc = tdp;
- tdp = ntdp;
- }
-
- if (tagadd(ii->ii_name, tid, tdp) < 0)
- return (-1);
- }
-
- ii->ii_type = II_TYPE;
- ii->ii_dtype = tdp;
- return (II_TYPE);
-}
-
-static iitype_t
-parse_sou(char *cp, iidesc_t *idp)
-{
- tdesc_t *rtdp;
- int tid;
-
- if (*cp++ != 'T')
- expected("parse_sou", "T (sou)", cp - 1);
-
- cp = id(cp, &tid);
- if (*cp++ != '=')
- expected("parse_sou", "= (definition)", cp - 1);
-
- parse_debug(1, NULL, "parse_sou: declaring '%s'", idp->ii_name ?
- idp->ii_name : "(anon)");
- if ((rtdp = lookup(tid)) != NULL) {
- if (idp->ii_name != NULL) {
- if (rtdp->t_name != NULL &&
- strcmp(rtdp->t_name, idp->ii_name) != 0) {
- tdesc_t *tdp;
-
- tdp = xcalloc(sizeof (*tdp));
- tdp->t_name = xstrdup(idp->ii_name);
- tdp->t_type = TYPEDEF;
- tdp->t_tdesc = rtdp;
- addhash(tdp, tid); /* for *(x,y) types */
- parse_debug(3, NULL, " %s defined as %s(%d)",
- idp->ii_name, tdesc_name(rtdp), tid);
- } else if (rtdp->t_name == NULL) {
- rtdp->t_name = xstrdup(idp->ii_name);
- addhash(rtdp, tid);
- }
- }
- } else {
- rtdp = xcalloc(sizeof (*rtdp));
- rtdp->t_name = idp->ii_name ? xstrdup(idp->ii_name) : NULL;
- addhash(rtdp, tid);
- }
-
- switch (*cp++) {
- case 's':
- (void) soudef(cp, STRUCT, &rtdp);
- break;
- case 'u':
- (void) soudef(cp, UNION, &rtdp);
- break;
- case 'e':
- enumdef(cp, &rtdp);
- break;
- default:
- expected("parse_sou", "<tag type s/u/e>", cp - 1);
- break;
- }
-
- idp->ii_type = II_SOU;
- idp->ii_dtype = rtdp;
- return (II_SOU);
-}
-
-int
-parse_stab(stab_t *stab, char *cp, iidesc_t **iidescp)
-{
- iidesc_t *ii = NULL;
- iitype_t (*parse)(char *, iidesc_t *);
- int rc;
-
- /*
- * set up for reset()
- */
- if (setjmp(resetbuf))
- return (-1);
-
- cp = whitesp(cp);
- ii = iidesc_new(NULL);
- cp = name(cp, &ii->ii_name);
-
- switch (stab->n_type) {
- case N_FUN:
- parse = parse_fun;
- break;
-
- case N_LSYM:
- if (*cp == 't')
- parse = parse_type;
- else if (*cp == 'T')
- parse = parse_sou;
- else
- parse = parse_sym;
- break;
-
- case N_GSYM:
- case N_LCSYM:
- case N_PSYM:
- case N_ROSYM:
- case N_RSYM:
- case N_STSYM:
- parse = parse_sym;
- break;
- default:
- parse_debug(1, cp, "Unknown stab type %#x", stab->n_type);
- bzero(&resetbuf, sizeof (resetbuf));
- return (-1);
- }
-
- rc = parse(cp, ii);
- bzero(&resetbuf, sizeof (resetbuf));
-
- if (rc < 0 || ii->ii_type == II_NOT) {
- iidesc_free(ii);
- return (rc);
- }
-
- *iidescp = ii;
-
- return (1);
-}
-
-/*
- * Check if we have this node in the hash table already
- */
-tdesc_t *
-lookup(int h)
-{
- int bucket = HASH(h);
- tdesc_t *tdp = hash_table[bucket];
-
- while (tdp != NULL) {
- if (tdp->t_id == h)
- return (tdp);
- tdp = tdp->t_hash;
- }
- return (NULL);
-}
-
-static char *
-whitesp(char *cp)
-{
- char c;
-
- for (c = *cp++; isspace(c); c = *cp++)
- ;
- --cp;
- return (cp);
-}
-
-static char *
-name(char *cp, char **w)
-{
- char *new, *orig, c;
- int len;
-
- orig = cp;
- c = *cp++;
- if (c == ':')
- *w = NULL;
- else if (isalpha(c) || strchr("_.$#", c)) {
- for (c = *cp++; isalnum(c) || strchr(" _.$#", c); c = *cp++)
- ;
- if (c != ':')
- reset();
- len = cp - orig;
- new = xmalloc(len);
- while (orig < cp - 1)
- *new++ = *orig++;
- *new = '\0';
- *w = new - (len - 1);
- } else
- reset();
-
- return (cp);
-}
-
-static char *
-number(char *cp, int *n)
-{
- char *next;
-
- *n = (int)strtol(cp, &next, 10);
- if (next == cp)
- expected("number", "<number>", cp);
- return (next);
-}
-
-static char *
-id(char *cp, int *h)
-{
- int n1, n2;
-
- if (*cp == '(') { /* SunPro style */
- cp++;
- cp = number(cp, &n1);
- if (*cp++ != ',')
- expected("id", ",", cp - 1);
- cp = number(cp, &n2);
- if (*cp++ != ')')
- expected("id", ")", cp - 1);
- *h = MAKETYPEID(n1, n2);
- } else if (isdigit(*cp)) { /* gcc style */
- cp = number(cp, &n1);
- *h = n1;
- } else {
- expected("id", "(/0-9", cp);
- }
- return (cp);
-}
-
-static int
-tagadd(char *w, int h, tdesc_t *tdp)
-{
- tdesc_t *otdp;
-
- tdp->t_name = w;
- if (!(otdp = lookup(h)))
- addhash(tdp, h);
- else if (otdp != tdp) {
- warning("duplicate entry\n");
- warning(" old: %s %d (%d,%d)\n", tdesc_name(otdp),
- otdp->t_type, TYPEFILE(otdp->t_id), TYPENUM(otdp->t_id));
- warning(" new: %s %d (%d,%d)\n", tdesc_name(tdp),
- tdp->t_type, TYPEFILE(tdp->t_id), TYPENUM(tdp->t_id));
- return (-1);
- }
-
- return (0);
-}
-
-static char *
-tdefdecl(char *cp, int h, tdesc_t **rtdp)
-{
- tdesc_t *ntdp;
- char *w;
- int c, h2;
- char type;
-
- parse_debug(3, cp, "tdefdecl h=%d", h);
-
- /* Type codes */
- switch (type = *cp) {
- case 'b': /* integer */
- case 'R': /* fp */
- cp = intrinsic(cp, rtdp);
- break;
- case '(': /* equiv to another type */
- cp = id(cp, &h2);
- ntdp = lookup(h2);
-
- if (ntdp != NULL && *cp == '=') {
- if (ntdp->t_type == FORWARD && *(cp + 1) == 'x') {
- /*
- * The 6.2 compiler, and possibly others, will
- * sometimes emit the same stab for a forward
- * declaration twice. That is, "(1,2)=xsfoo:"
- * will sometimes show up in two different
- * places. This is, of course, quite fun. We
- * want CTF to work in spite of the compiler,
- * so we'll let this one through.
- */
- char *c2 = cp + 2;
- char *nm;
-
- if (!strchr("sue", *c2++)) {
- expected("tdefdecl/x-redefine", "[sue]",
- c2 - 1);
- }
-
- c2 = name(c2, &nm);
- if (strcmp(nm, ntdp->t_name) != 0) {
- terminate("Stabs error: Attempt to "
- "redefine type (%d,%d) as "
- "something else: %s\n",
- TYPEFILE(h2), TYPENUM(h2),
- c2 - 1);
- }
- free(nm);
-
- h2 = faketypenumber++;
- ntdp = NULL;
- } else {
- terminate("Stabs error: Attempting to "
- "redefine type (%d,%d)\n", TYPEFILE(h2),
- TYPENUM(h2));
- }
- }
-
- if (ntdp == NULL) { /* if that type isn't defined yet */
- if (*cp != '=') {
- /* record it as unresolved */
- parse_debug(3, NULL, "tdefdecl unres type %d",
- h2);
- *rtdp = calloc(1, sizeof (**rtdp));
- (*rtdp)->t_type = TYPEDEF_UNRES;
- (*rtdp)->t_id = h2;
- break;
- } else
- cp++;
-
- /* define a new type */
- cp = tdefdecl(cp, h2, rtdp);
- if ((*rtdp)->t_id && (*rtdp)->t_id != h2) {
- ntdp = calloc(1, sizeof (*ntdp));
- ntdp->t_type = TYPEDEF;
- ntdp->t_tdesc = *rtdp;
- *rtdp = ntdp;
- }
-
- addhash(*rtdp, h2);
-
- } else { /* that type is already defined */
- if (ntdp->t_type != TYPEDEF || ntdp->t_name != NULL) {
- *rtdp = ntdp;
- } else {
- parse_debug(3, NULL,
- "No duplicate typedef anon for ref");
- *rtdp = ntdp;
- }
- }
- break;
- case '*':
- ntdp = NULL;
- cp = tdefdecl(cp + 1, h, &ntdp);
- if (ntdp == NULL)
- expected("tdefdecl/*", "id", cp);
-
- if (!ntdp->t_id)
- ntdp->t_id = faketypenumber++;
-
- *rtdp = xcalloc(sizeof (**rtdp));
- (*rtdp)->t_type = POINTER;
- (*rtdp)->t_size = 0;
- (*rtdp)->t_id = h;
- (*rtdp)->t_tdesc = ntdp;
- break;
- case 'f':
- cp = tdefdecl(cp + 1, h, &ntdp);
- *rtdp = xcalloc(sizeof (**rtdp));
- (*rtdp)->t_type = FUNCTION;
- (*rtdp)->t_size = 0;
- (*rtdp)->t_id = h;
- (*rtdp)->t_fndef = xcalloc(sizeof (fndef_t));
- /*
- * The 6.1 compiler will sometimes generate incorrect stabs for
- * function pointers (it'll get the return type wrong). This
- * causes merges to fail. We therefore treat function pointers
- * as if they all point to functions that return int. When
- * 4432549 is fixed, the lookupname() call below should be
- * replaced with `ntdp'.
- */
- (*rtdp)->t_fndef->fn_ret = lookupname("int");
- break;
- case 'a':
- case 'z':
- cp++;
- if (*cp++ != 'r')
- expected("tdefdecl/[az]", "r", cp - 1);
- *rtdp = xcalloc(sizeof (**rtdp));
- (*rtdp)->t_type = ARRAY;
- (*rtdp)->t_id = h;
- cp = arraydef(cp, rtdp);
- break;
- case 'x':
- c = *++cp;
- if (c != 's' && c != 'u' && c != 'e')
- expected("tdefdecl/x", "[sue]", cp - 1);
- cp = name(cp + 1, &w);
-
- ntdp = xcalloc(sizeof (*ntdp));
- ntdp->t_type = FORWARD;
- ntdp->t_name = w;
- /*
- * We explicitly don't set t_id here - the caller will do it.
- * The caller may want to use a real type ID, or they may
- * choose to make one up.
- */
-
- *rtdp = ntdp;
- break;
-
- case 'B': /* volatile */
- cp = tdefdecl(cp + 1, h, &ntdp);
-
- if (!ntdp->t_id)
- ntdp->t_id = faketypenumber++;
-
- *rtdp = xcalloc(sizeof (**rtdp));
- (*rtdp)->t_type = VOLATILE;
- (*rtdp)->t_size = 0;
- (*rtdp)->t_tdesc = ntdp;
- (*rtdp)->t_id = h;
- break;
-
- case 'k': /* const */
- cp = tdefdecl(cp + 1, h, &ntdp);
-
- if (!ntdp->t_id)
- ntdp->t_id = faketypenumber++;
-
- *rtdp = xcalloc(sizeof (**rtdp));
- (*rtdp)->t_type = CONST;
- (*rtdp)->t_size = 0;
- (*rtdp)->t_tdesc = ntdp;
- (*rtdp)->t_id = h;
- break;
-
- case 'K': /* restricted */
- cp = tdefdecl(cp + 1, h, &ntdp);
-
- if (!ntdp->t_id)
- ntdp->t_id = faketypenumber++;
-
- *rtdp = xcalloc(sizeof (**rtdp));
- (*rtdp)->t_type = RESTRICT;
- (*rtdp)->t_size = 0;
- (*rtdp)->t_tdesc = ntdp;
- (*rtdp)->t_id = h;
- break;
-
- case 'u':
- case 's':
- cp++;
-
- *rtdp = xcalloc(sizeof (**rtdp));
- (*rtdp)->t_name = NULL;
- cp = soudef(cp, (type == 'u') ? UNION : STRUCT, rtdp);
- break;
- default:
- expected("tdefdecl", "<type code>", cp);
- }
- return (cp);
-}
-
-static char *
-intrinsic(char *cp, tdesc_t **rtdp)
-{
- intr_t *intr = xcalloc(sizeof (intr_t));
- tdesc_t *tdp;
- int width, fmt, i;
-
- switch (*cp++) {
- case 'b':
- intr->intr_type = INTR_INT;
- if (*cp == 's')
- intr->intr_signed = 1;
- else if (*cp != 'u')
- expected("intrinsic/b", "[su]", cp);
- cp++;
-
- if (strchr("cbv", *cp))
- intr->intr_iformat = *cp++;
-
- cp = number(cp, &width);
- if (*cp++ != ';')
- expected("intrinsic/b", "; (post-width)", cp - 1);
-
- cp = number(cp, &intr->intr_offset);
- if (*cp++ != ';')
- expected("intrinsic/b", "; (post-offset)", cp - 1);
-
- cp = number(cp, &intr->intr_nbits);
- break;
-
- case 'R':
- intr->intr_type = INTR_REAL;
- for (fmt = 0, i = 0; isdigit(*(cp + i)); i++)
- fmt = fmt * 10 + (*(cp + i) - '0');
-
- if (fmt < 1 || fmt > CTF_FP_MAX)
- expected("intrinsic/R", "number <= CTF_FP_MAX", cp);
-
- intr->intr_fformat = fmt;
- cp += i;
-
- if (*cp++ != ';')
- expected("intrinsic/R", ";", cp - 1);
- cp = number(cp, &width);
-
- intr->intr_nbits = width * 8;
- break;
- }
-
- tdp = xcalloc(sizeof (*tdp));
- tdp->t_type = INTRINSIC;
- tdp->t_size = width;
- tdp->t_name = NULL;
- tdp->t_intr = intr;
- parse_debug(3, NULL, "intrinsic: size=%d", width);
- *rtdp = tdp;
-
- return (cp);
-}
-
-static tdesc_t *
-bitintrinsic(tdesc_t *template, int nbits)
-{
- tdesc_t *newtdp = xcalloc(sizeof (tdesc_t));
-
- newtdp->t_name = xstrdup(template->t_name);
- newtdp->t_id = faketypenumber++;
- newtdp->t_type = INTRINSIC;
- newtdp->t_size = template->t_size;
- newtdp->t_intr = xmalloc(sizeof (intr_t));
- bcopy(template->t_intr, newtdp->t_intr, sizeof (intr_t));
- newtdp->t_intr->intr_nbits = nbits;
-
- return (newtdp);
-}
-
-static char *
-offsize(char *cp, mlist_t *mlp)
-{
- int offset, size;
-
- if (*cp == ',')
- cp++;
- cp = number(cp, &offset);
- if (*cp++ != ',')
- expected("offsize/2", ",", cp - 1);
- cp = number(cp, &size);
- if (*cp++ != ';')
- expected("offsize/3", ";", cp - 1);
- mlp->ml_offset = offset;
- mlp->ml_size = size;
- return (cp);
-}
-
-static tdesc_t *
-find_intrinsic(tdesc_t *tdp)
-{
- for (;;) {
- switch (tdp->t_type) {
- case TYPEDEF:
- case VOLATILE:
- case CONST:
- case RESTRICT:
- tdp = tdp->t_tdesc;
- break;
-
- default:
- return (tdp);
- }
- }
-}
-
-static char *
-soudef(char *cp, stabtype_t type, tdesc_t **rtdp)
-{
- mlist_t *mlp, **prev;
- char *w;
- int h;
- int size;
- tdesc_t *tdp, *itdp;
-
- cp = number(cp, &size);
- (*rtdp)->t_size = size;
- (*rtdp)->t_type = type; /* s or u */
-
- /*
- * An '@' here indicates a bitmask follows. This is so the
- * compiler can pass information to debuggers about how structures
- * are passed in the v9 world. We don't need this information
- * so we skip over it.
- */
- if (cp[0] == '@') {
- cp += 3;
- }
-
- parse_debug(3, cp, "soudef: %s size=%d", tdesc_name(*rtdp),
- (*rtdp)->t_size);
-
- prev = &((*rtdp)->t_members);
- /* now fill up the fields */
- while ((*cp != '\0') && (*cp != ';')) { /* signifies end of fields */
- mlp = xcalloc(sizeof (*mlp));
- *prev = mlp;
- cp = name(cp, &w);
- mlp->ml_name = w;
- cp = id(cp, &h);
- /*
- * find the tdesc struct in the hash table for this type
- * and stick a ptr in here
- */
- tdp = lookup(h);
- if (tdp == NULL) { /* not in hash list */
- parse_debug(3, NULL, " defines %s (%d)", w, h);
- if (*cp++ != '=') {
- tdp = unres_new(h);
- parse_debug(3, NULL,
- " refers to %s (unresolved %d)",
- (w ? w : "anon"), h);
- } else {
- cp = tdefdecl(cp, h, &tdp);
-
- if (tdp->t_id && tdp->t_id != h) {
- tdesc_t *ntdp = xcalloc(sizeof (*ntdp));
-
- ntdp->t_type = TYPEDEF;
- ntdp->t_tdesc = tdp;
- tdp = ntdp;
- }
-
- addhash(tdp, h);
- parse_debug(4, cp,
- " soudef now looking at ");
- cp++;
- }
- } else {
- parse_debug(3, NULL, " refers to %s (%d, %s)",
- w ? w : "anon", h, tdesc_name(tdp));
- }
-
- cp = offsize(cp, mlp);
-
- itdp = find_intrinsic(tdp);
- if (itdp->t_type == INTRINSIC) {
- if (mlp->ml_size != itdp->t_intr->intr_nbits) {
- parse_debug(4, cp, "making %d bit intrinsic "
- "from %s", mlp->ml_size, tdesc_name(itdp));
- mlp->ml_type = bitintrinsic(itdp, mlp->ml_size);
- } else
- mlp->ml_type = tdp;
- } else if (itdp->t_type == TYPEDEF_UNRES) {
- list_add(&typedbitfldmems, mlp);
- mlp->ml_type = tdp;
- } else {
- mlp->ml_type = tdp;
- }
-
- /* cp is now pointing to next field */
- prev = &mlp->ml_next;
- }
- return (cp);
-}
-
-static char *
-arraydef(char *cp, tdesc_t **rtdp)
-{
- int start, end, h;
-
- cp = id(cp, &h);
- if (*cp++ != ';')
- expected("arraydef/1", ";", cp - 1);
-
- (*rtdp)->t_ardef = xcalloc(sizeof (ardef_t));
- (*rtdp)->t_ardef->ad_idxtype = lookup(h);
-
- cp = number(cp, &start); /* lower */
- if (*cp++ != ';')
- expected("arraydef/2", ";", cp - 1);
-
- if (*cp == 'S') {
- /*
- * variable length array - treat as null dimensioned
- *
- * For VLA variables on sparc, SS12 generated stab entry
- * looks as follows:
- * .stabs "buf:(0,28)=zr(0,4);0;S-12;(0,1)", 0x80, 0, 0, -16
- * Whereas SS12u1 generated stab entry looks like this:
- * .stabs "buf:(0,28)=zr(0,4);0;S0;(0,1)", 0x80, 0, 0, 0
- * On x86, both versions generate the first type of entry.
- * We should be able to parse both.
- */
- cp++;
- if (*cp == '-')
- cp++;
- cp = number(cp, &end);
- end = start;
- } else {
- /*
- * normal fixed-dimension array
- * Stab entry for this looks as follows :
- * .stabs "x:(0,28)=ar(0,4);0;9;(0,3)", 0x80, 0, 40, 0
- */
- cp = number(cp, &end); /* upper */
- }
-
- if (*cp++ != ';')
- expected("arraydef/3", ";", cp - 1);
- (*rtdp)->t_ardef->ad_nelems = end - start + 1;
- cp = tdefdecl(cp, h, &((*rtdp)->t_ardef->ad_contents));
-
- parse_debug(3, cp, "defined array idx type %d %d-%d next ",
- h, start, end);
-
- return (cp);
-}
-
-static void
-enumdef(char *cp, tdesc_t **rtdp)
-{
- elist_t *elp, **prev;
- char *w;
-
- (*rtdp)->t_type = ENUM;
- (*rtdp)->t_emem = NULL;
-
- prev = &((*rtdp)->t_emem);
- while (*cp != ';') {
- elp = xcalloc(sizeof (*elp));
- elp->el_next = NULL;
- *prev = elp;
- cp = name(cp, &w);
- elp->el_name = w;
- cp = number(cp, &elp->el_number);
- parse_debug(3, NULL, "enum %s: %s=%d", tdesc_name(*rtdp),
- elp->el_name, elp->el_number);
- prev = &elp->el_next;
- if (*cp++ != ',')
- expected("enumdef", ",", cp - 1);
- }
-}
-
-tdesc_t *
-lookup_name(tdesc_t **hash, const char *name)
-{
- int bucket = compute_sum(name);
- tdesc_t *tdp, *ttdp = NULL;
-
- for (tdp = hash[bucket]; tdp != NULL; tdp = tdp->t_next) {
- if (tdp->t_name != NULL && strcmp(tdp->t_name, name) == 0) {
- if (tdp->t_type == STRUCT || tdp->t_type == UNION ||
- tdp->t_type == ENUM || tdp->t_type == INTRINSIC)
- return (tdp);
- if (tdp->t_type == TYPEDEF)
- ttdp = tdp;
- }
- }
- return (ttdp);
-}
-
-tdesc_t *
-lookupname(const char *name)
-{
- return (lookup_name(name_table, name));
-}
-
-/*
- * Add a node to the hash queues.
- */
-static void
-addhash(tdesc_t *tdp, int num)
-{
- int hash = HASH(num);
- tdesc_t *ttdp;
- char added_num = 0, added_name = 0;
-
- /*
- * If it already exists in the hash table don't add it again
- * (but still check to see if the name should be hashed).
- */
- ttdp = lookup(num);
-
- if (ttdp == NULL) {
- tdp->t_id = num;
- tdp->t_hash = hash_table[hash];
- hash_table[hash] = tdp;
- added_num = 1;
- }
-
- if (tdp->t_name != NULL) {
- ttdp = lookupname(tdp->t_name);
- if (ttdp == NULL) {
- hash = compute_sum(tdp->t_name);
- tdp->t_next = name_table[hash];
- name_table[hash] = tdp;
- added_name = 1;
- }
- }
- if (!added_num && !added_name) {
- terminate("stabs: broken hash\n");
- }
-}
-
-static int
-compute_sum(const char *w)
-{
- char c;
- int sum;
-
- for (sum = 0; (c = *w) != '\0'; sum += c, w++)
- ;
- return (HASH(sum));
-}
-
-static void
-reset(void)
-{
- longjmp(resetbuf, 1);
-}
-
-void
-check_hash(void)
-{
- tdesc_t *tdp;
- int i;
-
- printf("checking hash\n");
- for (i = 0; i < BUCKETS; i++) {
- if (hash_table[i]) {
- for (tdp = hash_table[i]->t_hash;
- tdp && tdp != hash_table[i];
- tdp = tdp->t_hash)
- continue;
- if (tdp) {
- terminate("cycle in hash bucket %d\n", i);
- return;
- }
- }
-
- if (name_table[i]) {
- for (tdp = name_table[i]->t_next;
- tdp && tdp != name_table[i];
- tdp = tdp->t_next)
- continue;
- if (tdp) {
- terminate("cycle in name bucket %d\n", i);
- return;
- }
- }
- }
- printf("done\n");
-}
-
-/*ARGSUSED1*/
-static int
-resolve_typed_bitfields_cb(mlist_t *ml, void *private)
-{
- tdesc_t *tdp = ml->ml_type;
-
- debug(3, "Resolving typed bitfields (member %s)\n",
- (ml->ml_name ? ml->ml_name : "(anon)"));
-
- while (tdp) {
- switch (tdp->t_type) {
- case INTRINSIC:
- if (ml->ml_size != tdp->t_intr->intr_nbits) {
- debug(3, "making %d bit intrinsic from %s",
- ml->ml_size, tdesc_name(tdp));
- ml->ml_type = bitintrinsic(tdp, ml->ml_size);
- } else {
- debug(3, "using existing %d bit %s intrinsic",
- ml->ml_size, tdesc_name(tdp));
- ml->ml_type = tdp;
- }
- return (1);
-
- case POINTER:
- case TYPEDEF:
- case VOLATILE:
- case CONST:
- case RESTRICT:
- tdp = tdp->t_tdesc;
- break;
-
- default:
- return (1);
- }
- }
-
- terminate("type chain for bitfield member %s has a NULL", ml->ml_name);
- /*NOTREACHED*/
- return (0);
-}
-
-void
-resolve_typed_bitfields(void)
-{
- (void) list_iter(typedbitfldmems,
- (int (*)())resolve_typed_bitfields_cb, NULL);
-}
diff --git a/usr/src/tools/ctf/cvt/stabs.c b/usr/src/tools/ctf/cvt/stabs.c
deleted file mode 100644
index db6c8ae111..0000000000
--- a/usr/src/tools/ctf/cvt/stabs.c
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * 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) 2018, Joyent, Inc.
- */
-
-/*
- * Routines used to read stabs data from a file, and to build a tdata structure
- * based on the interesting parts of that data.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <assert.h>
-#include <string.h>
-#include <libgen.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/param.h>
-
-#include "ctftools.h"
-#include "list.h"
-#include "stack.h"
-#include "memory.h"
-#include "traverse.h"
-
-const char *curhdr;
-
-/*
- * The stabs generator will sometimes reference types before they've been
- * defined. If this is the case, a TYPEDEF_UNRES tdesc will be generated.
- * Note that this is different from a forward declaration, in which the
- * stab is defined, but is defined as something that doesn't exist yet.
- * When we have read all of the stabs from the file, we can go back and
- * fix up all of the unresolved types. We should be able to fix all of them.
- */
-/*ARGSUSED2*/
-static int
-resolve_tou_node(tdesc_t *node, tdesc_t **nodep, void *private)
-{
- tdesc_t *new;
-
- debug(3, "Trying to resolve %s (%d)\n", tdesc_name(node), node->t_id);
- new = lookup(node->t_id);
-
- if (new == NULL) {
- terminate("Couldn't resolve type %d\n", node->t_id);
- }
-
- debug(3, " Resolving to %d\n", new->t_id);
-
- *nodep = new;
-
- return (1);
-}
-
-/*ARGSUSED*/
-static int
-resolve_fwd_node(tdesc_t *node, tdesc_t **nodep, void *private)
-{
- tdesc_t *new = lookupname(node->t_name);
-
- debug(3, "Trying to unforward %s (%d)\n", tdesc_name(node), node->t_id);
-
- if (!new || (new->t_type != STRUCT && new->t_type != UNION))
- return (0);
-
- debug(3, " Unforwarded to %d\n", new->t_id);
-
- *nodep = new;
-
- return (1);
-}
-
-static tdtrav_cb_f resolve_cbs[] = {
- NULL,
- NULL, /* intrinsic */
- NULL, /* pointer */
- NULL, /* array */
- NULL, /* function */
- NULL, /* struct */
- NULL, /* union */
- NULL, /* enum */
- resolve_fwd_node, /* forward */
- NULL, /* typedef */
- resolve_tou_node, /* typedef unres */
- NULL, /* volatile */
- NULL, /* const */
- NULL, /* restrict */
-};
-
-static void
-resolve_nodes(tdata_t *td)
-{
- debug(2, "Resolving unresolved stabs\n");
-
- (void) iitraverse_hash(td->td_iihash, &td->td_curvgen, resolve_cbs,
- NULL, NULL, td);
-}
-
-static char *
-concat(char *s1, char *s2, int s2strip)
-{
- int savelen = strlen(s2) - s2strip;
- int newlen = (s1 ? strlen(s1) : 0) + savelen + 1;
- char *out;
-
- out = xrealloc(s1, newlen);
- if (s1)
- strncpy(out + strlen(out), s2, savelen);
- else
- strncpy(out, s2, savelen);
-
- out[newlen - 1] = '\0';
-
- return (out);
-}
-
-/*
- * N_FUN stabs come with their arguments in promoted form. In order to get the
- * actual arguments, we need to wait for the N_PSYM stabs that will come towards
- * the end of the function. These routines free the arguments (fnarg_free) we
- * got from the N_FUN stab and add (fnarg_add) the ones from the N_PSYM stabs.
- */
-static void
-fnarg_add(iidesc_t *curfun, iidesc_t *arg)
-{
- curfun->ii_nargs++;
-
- if (curfun->ii_nargs == 1)
- curfun->ii_args = xmalloc(sizeof (tdesc_t *) * FUNCARG_DEF);
- else if (curfun->ii_nargs > FUNCARG_DEF) {
- curfun->ii_args = xrealloc(curfun->ii_args,
- sizeof (tdesc_t *) * curfun->ii_nargs);
- }
-
- curfun->ii_args[curfun->ii_nargs - 1] = arg->ii_dtype;
- arg->ii_dtype = NULL;
-}
-
-static void
-fnarg_free(iidesc_t *ii)
-{
- ii->ii_nargs = 0;
- free(ii->ii_args);
- ii->ii_args = NULL;
-}
-
-/*
- * Read the stabs from the stab ELF section, and turn them into a tdesc tree,
- * assembled under an iidesc list.
- */
-int
-stabs_read(tdata_t *td, Elf *elf, const char *file)
-{
- Elf_Scn *scn;
- Elf_Data *data;
- stab_t *stab;
- stk_t *file_stack;
- iidesc_t *iidescp;
- iidesc_t *curfun = NULL;
- char curpath[MAXPATHLEN];
- char *curfile = NULL;
- char *str;
- char *fstr = NULL, *ofstr = NULL;
- int stabidx, stabstridx;
- int nstabs, rc, i;
- int scope = 0;
-
- if (!((stabidx = findelfsecidx(elf, file, ".stab.excl")) >= 0 &&
- (stabstridx = findelfsecidx(elf, file, ".stab.exclstr")) >= 0) &&
- !((stabidx = findelfsecidx(elf, file, ".stab")) >= 0 &&
- (stabstridx = findelfsecidx(elf, file, ".stabstr")) >= 0)) {
- errno = ENOENT;
- return (-1);
- }
-
- file_stack = stack_new(free);
-
- stack_push(file_stack, (void *)file);
- curhdr = file;
-
- debug(3, "Found stabs in %d, strings in %d\n", stabidx, stabstridx);
-
- scn = elf_getscn(elf, stabidx);
- data = elf_rawdata(scn, NULL);
- nstabs = data->d_size / sizeof (stab_t);
-
- parse_init(td);
- for (i = 0; i < nstabs; i++) {
- stab = &((stab_t *)data->d_buf)[i];
-
- /* We don't want any local definitions */
- if (stab->n_type == N_LBRAC) {
- scope++;
- debug(3, "stab %d: opening scope (%d)\n", i + 1, scope);
- continue;
- } else if (stab->n_type == N_RBRAC) {
- scope--;
- debug(3, "stab %d: closing scope (%d)\n", i + 1, scope);
- continue;
- } else if (stab->n_type == N_EINCL) {
- /*
- * There's a bug in the 5.2 (Taz) compilers that causes
- * them to emit an extra N_EINCL if there's no actual
- * text in the file being compiled. To work around this
- * bug, we explicitly check to make sure we're not
- * trying to pop a stack that only has the outer scope
- * on it.
- */
- if (stack_level(file_stack) != 1) {
- str = (char *)stack_pop(file_stack);
- free(str);
- curhdr = (char *)stack_peek(file_stack);
- }
- }
-
- /* We only care about a subset of the stabs */
- if (!(stab->n_type == N_FUN || stab->n_type == N_GSYM ||
- stab->n_type == N_LCSYM || stab->n_type == N_LSYM ||
- stab->n_type == N_PSYM || stab->n_type == N_ROSYM ||
- stab->n_type == N_RSYM ||
- stab->n_type == N_STSYM || stab->n_type == N_BINCL ||
- stab->n_type == N_SO || stab->n_type == N_OPT))
- continue;
-
- if ((str = elf_strptr(elf, stabstridx,
- (size_t)stab->n_strx)) == NULL) {
- terminate("%s: Can't find string at %u for stab %d\n",
- file, stab->n_strx, i);
- }
-
- if (stab->n_type == N_BINCL) {
- curhdr = xstrdup(str);
- stack_push(file_stack, (void *)curhdr);
- continue;
- } else if (stab->n_type == N_SO) {
- if (str[strlen(str) - 1] != '/') {
- strcpy(curpath, str);
- curfile = basename(curpath);
- }
- continue;
- } else if (stab->n_type == N_OPT) {
- if (strcmp(str, "gcc2_compiled.") == 0) {
- terminate("%s: GCC-generated stabs are "
- "unsupported. Use DWARF instead.\n", file);
- }
- continue;
- }
-
- if (str[strlen(str) - 1] == '\\') {
- int offset = 1;
- /*
- * There's a bug in the compilers that causes them to
- * generate \ for continuations with just -g (this is
- * ok), and \\ for continuations with -g -O (this is
- * broken). This bug is "fixed" in the 6.2 compilers
- * via the elimination of continuation stabs.
- */
- if (str[strlen(str) - 2] == '\\')
- offset = 2;
- fstr = concat(fstr, str, offset);
- continue;
- } else
- fstr = concat(fstr, str, 0);
-
- debug(3, "%4d: .stabs \"%s\", %#x, %d, %hd, %d (from %s)\n", i,
- fstr, stab->n_type, 0, stab->n_desc,
- stab->n_value, curhdr);
-
- if (debug_level >= 3)
- check_hash();
-
- /*
- * Sometimes the compiler stutters, and emits the same stab
- * twice. This is bad for the parser, which will attempt to
- * redefine the type IDs indicated in the stabs. This is
- * compiler bug 4433511.
- */
- if (ofstr && strcmp(fstr, ofstr) == 0) {
- debug(3, "Stutter stab\n");
- free(fstr);
- fstr = NULL;
- continue;
- }
-
- if (ofstr)
- free(ofstr);
- ofstr = fstr;
-
- iidescp = NULL;
-
- if ((rc = parse_stab(stab, fstr, &iidescp)) < 0) {
- terminate("%s: Couldn't parse stab \"%s\" "
- "(source file %s)\n", file, str, curhdr);
- }
-
- if (rc == 0)
- goto parse_loop_end;
-
- /* Make sure the scope tracking is working correctly */
- assert(stab->n_type != N_FUN || (iidescp->ii_type != II_GFUN &&
- iidescp->ii_type != II_SFUN) || scope == 0);
-
- /*
- * The only things we care about that are in local scope are
- * the N_PSYM stabs.
- */
- if (scope && stab->n_type != N_PSYM) {
- iidesc_free(iidescp);
- goto parse_loop_end;
- }
-
- switch (iidescp->ii_type) {
- case II_SFUN:
- iidescp->ii_owner = xstrdup(curfile);
- /*FALLTHROUGH*/
- case II_GFUN:
- curfun = iidescp;
- fnarg_free(iidescp);
- iidesc_add(td->td_iihash, iidescp);
- break;
-
- case II_SVAR:
- iidescp->ii_owner = xstrdup(curfile);
- /*FALLTHROUGH*/
- case II_GVAR:
- case II_TYPE:
- case II_SOU:
- iidesc_add(td->td_iihash, iidescp);
- break;
-
- case II_PSYM:
- fnarg_add(curfun, iidescp);
- iidesc_free(iidescp);
- break;
- default:
- aborterr("invalid ii_type %d for stab type %d",
- iidescp->ii_type, stab->n_type);
- }
-
-parse_loop_end:
- fstr = NULL;
- }
-
- if (ofstr)
- free(ofstr);
-
- resolve_nodes(td);
- resolve_typed_bitfields();
- parse_finish(td);
-
- cvt_fixstabs(td);
- cvt_fixups(td, elf_ptrsz(elf));
-
- return (0);
-}
diff --git a/usr/src/tools/ctf/cvt/stack.c b/usr/src/tools/ctf/cvt/stack.c
deleted file mode 100644
index 7c36cd5ef1..0000000000
--- a/usr/src/tools/ctf/cvt/stack.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Routines for manipulating stacks
- */
-
-#include <stdio.h>
-#include <assert.h>
-#include <stdlib.h>
-
-#include "stack.h"
-#include "memory.h"
-
-#define STACK_SEEDSIZE 5
-
-struct stk {
- int st_nument;
- int st_top;
- void **st_data;
-
- void (*st_free)(void *);
-};
-
-stk_t *
-stack_new(void (*freep)(void *))
-{
- stk_t *sp;
-
- sp = xmalloc(sizeof (stk_t));
- sp->st_nument = STACK_SEEDSIZE;
- sp->st_top = -1;
- sp->st_data = xmalloc(sizeof (void *) * sp->st_nument);
- sp->st_free = freep;
-
- return (sp);
-}
-
-void
-stack_free(stk_t *sp)
-{
- int i;
-
- if (sp->st_free) {
- for (i = 0; i <= sp->st_top; i++)
- sp->st_free(sp->st_data[i]);
- }
- free(sp->st_data);
- free(sp);
-}
-
-void *
-stack_pop(stk_t *sp)
-{
- assert(sp->st_top >= 0);
-
- return (sp->st_data[sp->st_top--]);
-}
-
-void *
-stack_peek(stk_t *sp)
-{
- if (sp->st_top == -1)
- return (NULL);
-
- return (sp->st_data[sp->st_top]);
-}
-
-void
-stack_push(stk_t *sp, void *data)
-{
- sp->st_top++;
-
- if (sp->st_top == sp->st_nument) {
- sp->st_nument += STACK_SEEDSIZE;
- sp->st_data = xrealloc(sp->st_data,
- sizeof (void *) * sp->st_nument);
- }
-
- sp->st_data[sp->st_top] = data;
-}
-
-int
-stack_level(stk_t *sp)
-{
- return (sp->st_top + 1);
-}
diff --git a/usr/src/tools/ctf/cvt/stack.h b/usr/src/tools/ctf/cvt/stack.h
deleted file mode 100644
index 7dca7cfb10..0000000000
--- a/usr/src/tools/ctf/cvt/stack.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef _STACK_H
-#define _STACK_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Routines for manipulating stacks
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct stk stk_t;
-
-stk_t *stack_new(void (*)(void *));
-void stack_free(stk_t *);
-void *stack_pop(stk_t *);
-void *stack_peek(stk_t *);
-void stack_push(stk_t *, void *);
-int stack_level(stk_t *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _STACK_H */
diff --git a/usr/src/tools/ctf/cvt/strtab.c b/usr/src/tools/ctf/cvt/strtab.c
deleted file mode 100644
index ba6b7d86d0..0000000000
--- a/usr/src/tools/ctf/cvt/strtab.c
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * 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.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <sys/types.h>
-#include <sys/sysmacros.h>
-#include <strings.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "strtab.h"
-#include "memory.h"
-
-#define STRTAB_HASHSZ 211 /* use a prime number of hash buckets */
-#define STRTAB_BUFSZ (64 * 1024) /* use 64K data buffers by default */
-
-static void
-strtab_grow(strtab_t *sp)
-{
- sp->str_nbufs++;
- sp->str_bufs = xrealloc(sp->str_bufs, sp->str_nbufs * sizeof (char *));
- sp->str_ptr = xmalloc(sp->str_bufsz);
- sp->str_bufs[sp->str_nbufs - 1] = sp->str_ptr;
-}
-
-void
-strtab_create(strtab_t *sp)
-{
- sp->str_hash = xcalloc(STRTAB_HASHSZ * sizeof (strhash_t *));
- sp->str_hashsz = STRTAB_HASHSZ;
- sp->str_bufs = NULL;
- sp->str_ptr = NULL;
- sp->str_nbufs = 0;
- sp->str_bufsz = STRTAB_BUFSZ;
- sp->str_nstrs = 1;
- sp->str_size = 1;
-
- strtab_grow(sp);
- *sp->str_ptr++ = '\0';
-}
-
-void
-strtab_destroy(strtab_t *sp)
-{
- strhash_t *hp, *hq;
- ulong_t i;
-
- for (i = 0; i < sp->str_hashsz; i++) {
- for (hp = sp->str_hash[i]; hp != NULL; hp = hq) {
- hq = hp->str_next;
- free(hp);
- }
- }
-
- for (i = 0; i < sp->str_nbufs; i++)
- free(sp->str_bufs[i]);
-
- free(sp->str_hash);
- free(sp->str_bufs);
-}
-
-static ulong_t
-strtab_hash(const char *key, size_t *len)
-{
- ulong_t g, h = 0;
- const char *p;
- size_t n = 0;
-
- for (p = key; *p != '\0'; p++, n++) {
- h = (h << 4) + *p;
-
- if ((g = (h & 0xf0000000)) != 0) {
- h ^= (g >> 24);
- h ^= g;
- }
- }
-
- *len = n;
- return (h);
-}
-
-static int
-strtab_compare(strtab_t *sp, strhash_t *hp, const char *str, size_t len)
-{
- ulong_t b = hp->str_buf;
- const char *buf = hp->str_data;
- size_t resid, n;
- int rv;
-
- while (len != 0) {
- if (buf == sp->str_bufs[b] + sp->str_bufsz)
- buf = sp->str_bufs[++b];
-
- resid = sp->str_bufs[b] + sp->str_bufsz - buf;
- n = MIN(resid, len);
-
- if ((rv = strncmp(buf, str, n)) != 0)
- return (rv);
-
- buf += n;
- str += n;
- len -= n;
- }
-
- return (0);
-}
-
-static void
-strtab_copyin(strtab_t *sp, const char *str, size_t len)
-{
- ulong_t b = sp->str_nbufs - 1;
- size_t resid, n;
-
- while (len != 0) {
- if (sp->str_ptr == sp->str_bufs[b] + sp->str_bufsz) {
- strtab_grow(sp);
- b++;
- }
-
- resid = sp->str_bufs[b] + sp->str_bufsz - sp->str_ptr;
- n = MIN(resid, len);
- bcopy(str, sp->str_ptr, n);
-
- sp->str_ptr += n;
- str += n;
- len -= n;
- }
-}
-
-size_t
-strtab_insert(strtab_t *sp, const char *str)
-{
- strhash_t *hp;
- size_t len;
- ulong_t h;
-
- if (str == NULL || str[0] == '\0')
- return (0); /* we keep a \0 at offset 0 to simplify things */
-
- h = strtab_hash(str, &len) % sp->str_hashsz;
-
- /*
- * If the string is already in our hash table, just return the offset
- * of the existing string element and do not add a duplicate string.
- */
- for (hp = sp->str_hash[h]; hp != NULL; hp = hp->str_next) {
- if (strtab_compare(sp, hp, str, len + 1) == 0)
- return (hp->str_off);
- }
-
- /*
- * Create a new hash bucket, initialize it, and insert it at the front
- * of the hash chain for the appropriate bucket.
- */
- hp = xmalloc(sizeof (strhash_t));
-
- hp->str_data = sp->str_ptr;
- hp->str_buf = sp->str_nbufs - 1;
- hp->str_off = sp->str_size;
- hp->str_len = len;
- hp->str_next = sp->str_hash[h];
-
- sp->str_hash[h] = hp;
-
- /*
- * Now copy the string data into our buffer list, and then update
- * the global counts of strings and bytes. Return str's byte offset.
- */
- strtab_copyin(sp, str, len + 1);
- sp->str_nstrs++;
- sp->str_size += len + 1;
-
- return (hp->str_off);
-}
-
-size_t
-strtab_size(const strtab_t *sp)
-{
- return (sp->str_size);
-}
-
-ssize_t
-strtab_write(const strtab_t *sp,
- ssize_t (*func)(const void *, size_t, void *), void *priv)
-{
- ssize_t res, total = 0;
- ulong_t i;
- size_t n;
-
- for (i = 0; i < sp->str_nbufs; i++, total += res) {
- if (i == sp->str_nbufs - 1)
- n = sp->str_ptr - sp->str_bufs[i];
- else
- n = sp->str_bufsz;
-
- if ((res = func(sp->str_bufs[i], n, priv)) <= 0)
- break;
- }
-
- if (total == 0 && sp->str_size != 0)
- return (-1);
-
- return (total);
-}
-
-void
-strtab_print(const strtab_t *sp)
-{
- const strhash_t *hp;
- ulong_t i;
-
- for (i = 0; i < sp->str_hashsz; i++) {
- for (hp = sp->str_hash[i]; hp != NULL; hp = hp->str_next) {
- const char *buf = hp->str_data;
- ulong_t b = hp->str_buf;
- size_t resid, len, n;
-
- (void) printf("[%lu] %lu \"", (ulong_t)hp->str_off, b);
-
- for (len = hp->str_len; len != 0; len -= n) {
- if (buf == sp->str_bufs[b] + sp->str_bufsz)
- buf = sp->str_bufs[++b];
-
- resid = sp->str_bufs[b] + sp->str_bufsz - buf;
- n = MIN(resid, len);
-
- (void) printf("%.*s", (int)n, buf);
- buf += n;
- }
-
- (void) printf("\"\n");
- }
- }
-}
diff --git a/usr/src/tools/ctf/cvt/strtab.h b/usr/src/tools/ctf/cvt/strtab.h
deleted file mode 100644
index 7176e07378..0000000000
--- a/usr/src/tools/ctf/cvt/strtab.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef _STRTAB_H
-#define _STRTAB_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <sys/types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct strhash {
- const char *str_data; /* pointer to actual string data */
- ulong_t str_buf; /* index of string data buffer */
- size_t str_off; /* offset in bytes of this string */
- size_t str_len; /* length in bytes of this string */
- struct strhash *str_next; /* next string in hash chain */
-} strhash_t;
-
-typedef struct strtab {
- strhash_t **str_hash; /* array of hash buckets */
- ulong_t str_hashsz; /* size of hash bucket array */
- char **str_bufs; /* array of buffer pointers */
- char *str_ptr; /* pointer to current buffer location */
- ulong_t str_nbufs; /* size of buffer pointer array */
- size_t str_bufsz; /* size of individual buffer */
- ulong_t str_nstrs; /* total number of strings in strtab */
- size_t str_size; /* total size of strings in bytes */
-} strtab_t;
-
-extern void strtab_create(strtab_t *);
-extern void strtab_destroy(strtab_t *);
-extern size_t strtab_insert(strtab_t *, const char *);
-extern size_t strtab_size(const strtab_t *);
-extern ssize_t strtab_write(const strtab_t *,
- ssize_t (*)(const void *, size_t, void *), void *);
-extern void strtab_print(const strtab_t *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _STRTAB_H */
diff --git a/usr/src/tools/ctf/cvt/tdata.c b/usr/src/tools/ctf/cvt/tdata.c
deleted file mode 100644
index ca71168bcf..0000000000
--- a/usr/src/tools/ctf/cvt/tdata.c
+++ /dev/null
@@ -1,479 +0,0 @@
-/*
- * 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 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * Routines for manipulating tdesc and tdata structures
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <pthread.h>
-
-#include "ctftools.h"
-#include "memory.h"
-#include "traverse.h"
-
-/*
- * The layout hash is used during the equivalency checking. We have a node in
- * the child graph that may be equivalent to a node in the parent graph. To
- * find the corresponding node (if any) in the parent, we need a quick way to
- * get to all nodes in the parent that look like the node in the child. Since a
- * large number of nodes don't have names, we need to incorporate the layout of
- * the node into the hash. If we don't, we'll end up with the vast majority of
- * nodes in bucket zero, with one or two nodes in each of the remaining buckets.
- *
- * There are a couple of constraints, both of which concern forward
- * declarations. Recall that a forward declaration tdesc is equivalent to a
- * tdesc that actually defines the structure or union. As such, we cannot
- * incorporate anything into the hash for a named struct or union node that
- * couldn't be found by looking at the forward, and vice versa.
- */
-int
-tdesc_layouthash(int nbuckets, void *node)
-{
- tdesc_t *tdp = node;
- char *name = NULL;
- ulong_t h = 0;
-
- if (tdp->t_name)
- name = tdp->t_name;
- else {
- switch (tdp->t_type) {
- case POINTER:
- case TYPEDEF:
- case VOLATILE:
- case CONST:
- case RESTRICT:
- name = tdp->t_tdesc->t_name;
- break;
- case FUNCTION:
- h = tdp->t_fndef->fn_nargs +
- tdp->t_fndef->fn_vargs;
- name = tdp->t_fndef->fn_ret->t_name;
- break;
- case ARRAY:
- h = tdp->t_ardef->ad_nelems;
- name = tdp->t_ardef->ad_contents->t_name;
- break;
- case STRUCT:
- case UNION:
- /*
- * Unnamed structures, which cannot have forward
- * declarations pointing to them. We can therefore
- * incorporate the name of the first member into
- * the hash value, assuming there are any.
- */
- if (tdp->t_members != NULL)
- name = tdp->t_members->ml_name;
- break;
- case ENUM:
- /* Use the first element in the hash value */
- name = tdp->t_emem->el_name;
- break;
- default:
- /*
- * Intrinsics, forwards, and typedefs all have
- * names.
- */
- warning("Unexpected unnamed %d tdesc (ID %d)\n",
- tdp->t_type, tdp->t_id);
- }
- }
-
- if (name)
- return (hash_name(nbuckets, name));
-
- return (h % nbuckets);
-}
-
-int
-tdesc_layoutcmp(void *arg1, void *arg2)
-{
- tdesc_t *tdp1 = arg1, *tdp2 = arg2;
-
- if (tdp1->t_name == NULL) {
- if (tdp2->t_name == NULL)
- return (0);
- else
- return (-1);
- } else if (tdp2->t_name == NULL)
- return (1);
- else
- return (strcmp(tdp1->t_name, tdp2->t_name));
-}
-
-int
-tdesc_idhash(int nbuckets, void *data)
-{
- tdesc_t *tdp = data;
-
- return (tdp->t_id % nbuckets);
-}
-
-int
-tdesc_idcmp(void *arg1, void *arg2)
-{
- tdesc_t *tdp1 = arg1, *tdp2 = arg2;
-
- if (tdp1->t_id == tdp2->t_id)
- return (0);
- else
- return (tdp1->t_id > tdp2->t_id ? 1 : -1);
-}
-
-int
-tdesc_namehash(int nbuckets, void *data)
-{
- tdesc_t *tdp = data;
- ulong_t h, g;
- char *c;
-
- if (tdp->t_name == NULL)
- return (0);
-
- for (h = 0, c = tdp->t_name; *c; c++) {
- h = (h << 4) + *c;
- if ((g = (h & 0xf0000000)) != 0) {
- h ^= (g >> 24);
- h ^= g;
- }
- }
-
- return (h % nbuckets);
-}
-
-int
-tdesc_namecmp(void *arg1, void *arg2)
-{
- tdesc_t *tdp1 = arg1, *tdp2 = arg2;
-
- return (!streq(tdp1->t_name, tdp2->t_name));
-}
-
-/*ARGSUSED1*/
-int
-tdesc_print(void *data, void *private)
-{
- tdesc_t *tdp = data;
-
- printf("%7d %s\n", tdp->t_id, tdesc_name(tdp));
-
- return (1);
-}
-
-static void
-free_intr(tdesc_t *tdp)
-{
- free(tdp->t_intr);
-}
-
-static void
-free_ardef(tdesc_t *tdp)
-{
- free(tdp->t_ardef);
-}
-
-static void
-free_mlist(tdesc_t *tdp)
-{
- mlist_t *ml = tdp->t_members;
- mlist_t *oml;
-
- while (ml) {
- oml = ml;
- ml = ml->ml_next;
-
- if (oml->ml_name)
- free(oml->ml_name);
- free(oml);
- }
-}
-
-static void
-free_elist(tdesc_t *tdp)
-{
- elist_t *el = tdp->t_emem;
- elist_t *oel;
-
- while (el) {
- oel = el;
- el = el->el_next;
-
- if (oel->el_name)
- free(oel->el_name);
- free(oel);
- }
-}
-
-static void (*free_cbs[])(tdesc_t *) = {
- NULL,
- free_intr,
- NULL,
- free_ardef,
- NULL,
- free_mlist,
- free_mlist,
- free_elist,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
-};
-
-/*ARGSUSED1*/
-static void
-tdesc_free_cb(void *ptr, void *private)
-{
- tdesc_t *tdp = ptr;
-
- if (tdp->t_name)
- free(tdp->t_name);
- if (free_cbs[tdp->t_type])
- free_cbs[tdp->t_type](tdp);
- free(tdp);
-}
-
-void
-tdesc_free(tdesc_t *tdp)
-{
- tdesc_free_cb(tdp, NULL);
-}
-
-static int
-tdata_label_cmp(labelent_t *le1, labelent_t *le2)
-{
- return (le1->le_idx - le2->le_idx);
-}
-
-void
-tdata_label_add(tdata_t *td, char *label, int idx)
-{
- labelent_t *le = xmalloc(sizeof (*le));
-
- le->le_name = xstrdup(label);
- le->le_idx = (idx == -1 ? td->td_nextid - 1 : idx);
-
- slist_add(&td->td_labels, le, (int (*)())tdata_label_cmp);
-}
-
-static int
-tdata_label_top_cb(void *data, void *arg)
-{
- labelent_t *le = data;
- labelent_t **topp = arg;
-
- *topp = le;
-
- return (1);
-}
-
-labelent_t *
-tdata_label_top(tdata_t *td)
-{
- labelent_t *top = NULL;
-
- (void) list_iter(td->td_labels, tdata_label_top_cb, &top);
-
- return (top);
-}
-
-static int
-tdata_label_find_cb(labelent_t *le, labelent_t *tmpl)
-{
- return (streq(le->le_name, tmpl->le_name));
-}
-
-int
-tdata_label_find(tdata_t *td, char *label)
-{
- labelent_t let;
- labelent_t *ret;
-
- if (streq(label, "BASE")) {
- ret = (labelent_t *)list_first(td->td_labels);
- return (ret ? ret->le_idx : -1);
- }
-
- let.le_name = label;
-
- if (!(ret = (labelent_t *)list_find(td->td_labels, &let,
- (int (*)())tdata_label_find_cb)))
- return (-1);
-
- return (ret->le_idx);
-}
-
-static int
-tdata_label_newmax_cb(void *data, void *arg)
-{
- labelent_t *le = data;
- int *newmaxp = arg;
-
- if (le->le_idx > *newmaxp) {
- le->le_idx = *newmaxp;
- return (1);
- }
-
- return (0);
-}
-
-void
-tdata_label_newmax(tdata_t *td, int newmax)
-{
- (void) list_iter(td->td_labels, tdata_label_newmax_cb, &newmax);
-}
-
-/*ARGSUSED1*/
-static void
-tdata_label_free_cb(labelent_t *le, void *private)
-{
- if (le->le_name)
- free(le->le_name);
- free(le);
-}
-
-void
-tdata_label_free(tdata_t *td)
-{
- list_free(td->td_labels, (void (*)())tdata_label_free_cb, NULL);
- td->td_labels = NULL;
-}
-
-tdata_t *
-tdata_new(void)
-{
- tdata_t *new = xcalloc(sizeof (tdata_t));
-
- new->td_layouthash = hash_new(TDATA_LAYOUT_HASH_SIZE, tdesc_layouthash,
- tdesc_layoutcmp);
- new->td_idhash = hash_new(TDATA_ID_HASH_SIZE, tdesc_idhash,
- tdesc_idcmp);
- /*
- * This is also traversed as a list, but amortized O(1)
- * lookup massively impacts part of the merge phase, so
- * we store the iidescs as a hash.
- */
- new->td_iihash = hash_new(IIDESC_HASH_SIZE, iidesc_hash, NULL);
- new->td_nextid = 1;
- new->td_curvgen = 1;
-
- pthread_mutex_init(&new->td_mergelock, NULL);
-
- return (new);
-}
-
-void
-tdata_free(tdata_t *td)
-{
- hash_free(td->td_iihash, iidesc_free_cb, NULL);
- hash_free(td->td_layouthash, tdesc_free_cb, NULL);
- hash_free(td->td_idhash, NULL, NULL);
- list_free(td->td_fwdlist, NULL, NULL);
-
- tdata_label_free(td);
-
- free(td->td_parlabel);
- free(td->td_parname);
-
- pthread_mutex_destroy(&td->td_mergelock);
-
- free(td);
-}
-
-/*ARGSUSED1*/
-static int
-build_hashes(tdesc_t *ctdp, tdesc_t **ctdpp, void *private)
-{
- tdata_t *td = private;
-
- hash_add(td->td_idhash, ctdp);
- hash_add(td->td_layouthash, ctdp);
-
- return (1);
-}
-
-static tdtrav_cb_f build_hashes_cbs[] = {
- NULL,
- build_hashes, /* intrinsic */
- build_hashes, /* pointer */
- build_hashes, /* array */
- build_hashes, /* function */
- build_hashes, /* struct */
- build_hashes, /* union */
- build_hashes, /* enum */
- build_hashes, /* forward */
- build_hashes, /* typedef */
- tdtrav_assert, /* typedef_unres */
- build_hashes, /* volatile */
- build_hashes, /* const */
- build_hashes /* restrict */
-};
-
-static void
-tdata_build_hashes_common(tdata_t *td, hash_t *hash)
-{
- (void) iitraverse_hash(hash, &td->td_curvgen, NULL, NULL,
- build_hashes_cbs, td);
-}
-
-void
-tdata_build_hashes(tdata_t *td)
-{
- tdata_build_hashes_common(td, td->td_iihash);
-}
-
-/* Merge td2 into td1. td2 is destroyed by the merge */
-void
-tdata_merge(tdata_t *td1, tdata_t *td2)
-{
- td1->td_curemark = MAX(td1->td_curemark, td2->td_curemark);
- td1->td_curvgen = MAX(td1->td_curvgen, td2->td_curvgen);
- td1->td_nextid = MAX(td1->td_nextid, td2->td_nextid);
-
- hash_merge(td1->td_iihash, td2->td_iihash);
-
- /* Add td2's type tree to the hashes */
- tdata_build_hashes_common(td1, td2->td_iihash);
-
- list_concat(&td1->td_fwdlist, td2->td_fwdlist);
- td2->td_fwdlist = NULL;
-
- slist_merge(&td1->td_labels, td2->td_labels,
- (int (*)())tdata_label_cmp);
- td2->td_labels = NULL;
-
- /* free the td2 hashes (data is now part of td1) */
-
- hash_free(td2->td_layouthash, NULL, NULL);
- td2->td_layouthash = NULL;
-
- hash_free(td2->td_iihash, NULL, NULL);
- td2->td_iihash = NULL;
-
- tdata_free(td2);
-}
diff --git a/usr/src/tools/ctf/cvt/traverse.c b/usr/src/tools/ctf/cvt/traverse.c
deleted file mode 100644
index b415b35af6..0000000000
--- a/usr/src/tools/ctf/cvt/traverse.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * 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.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Routines used to traverse tdesc trees, invoking user-supplied callbacks
- * as the tree is traversed.
- */
-
-#include <stdio.h>
-#include <assert.h>
-
-#include "ctftools.h"
-#include "traverse.h"
-#include "memory.h"
-
-int (*tddescenders[])();
-int (*tdnops[])();
-
-int tdtraverse(tdesc_t *, tdesc_t **, tdtrav_data_t *);
-
-void
-tdtrav_init(tdtrav_data_t *tdtd, int *vgenp, tdtrav_cb_f *firstops,
- tdtrav_cb_f *preops, tdtrav_cb_f *postops, void *private)
-{
- tdtd->vgen = ++(*vgenp);
- tdtd->firstops = firstops ? firstops : tdnops;
- tdtd->preops = preops ? preops : tdnops;
- tdtd->postops = postops ? postops : tdnops;
- tdtd->private = private;
-}
-
-static int
-tdtrav_plain(tdesc_t *this, tdtrav_data_t *tdtd)
-{
- return (tdtraverse(this->t_tdesc, &this->t_tdesc, tdtd));
-}
-
-static int
-tdtrav_func(tdesc_t *this, tdtrav_data_t *tdtd)
-{
- fndef_t *fn = this->t_fndef;
- int i, rc;
-
- if ((rc = tdtraverse(fn->fn_ret, &fn->fn_ret, tdtd)) < 0)
- return (rc);
-
- for (i = 0; i < fn->fn_nargs; i++) {
- if ((rc = tdtraverse(fn->fn_args[i], &fn->fn_args[i],
- tdtd)) < 0)
- return (rc);
- }
-
- return (0);
-}
-
-static int
-tdtrav_array(tdesc_t *this, tdtrav_data_t *tdtd)
-{
- ardef_t *ardef = this->t_ardef;
- int rc;
-
- if ((rc = tdtraverse(ardef->ad_contents, &ardef->ad_contents,
- tdtd)) < 0)
- return (rc);
-
- return (tdtraverse(ardef->ad_idxtype, &ardef->ad_idxtype, tdtd));
-}
-
-static int
-tdtrav_su(tdesc_t *this, tdtrav_data_t *tdtd)
-{
- mlist_t *ml;
- int rc = 0;
-
- for (ml = this->t_members; ml; ml = ml->ml_next) {
- if ((rc = tdtraverse(ml->ml_type, &ml->ml_type, tdtd)) < 0)
- return (rc);
- }
-
- return (rc);
-}
-
-/*ARGSUSED*/
-int
-tdtrav_assert(tdesc_t *node, tdesc_t **nodep, void *private)
-{
- assert(1 == 0);
-
- return (-1);
-}
-
-tdtrav_cb_f tdnops[] = {
- NULL,
- NULL, /* intrinsic */
- NULL, /* pointer */
- NULL, /* array */
- NULL, /* function */
- NULL, /* struct */
- NULL, /* union */
- NULL, /* enum */
- NULL, /* forward */
- NULL, /* typedef */
- NULL, /* typedef_unres */
- NULL, /* volatile */
- NULL, /* const */
- NULL /* restrict */
-};
-
-int (*tddescenders[])(tdesc_t *, tdtrav_data_t *) = {
- NULL,
- NULL, /* intrinsic */
- tdtrav_plain, /* pointer */
- tdtrav_array, /* array */
- tdtrav_func, /* function */
- tdtrav_su, /* struct */
- tdtrav_su, /* union */
- NULL, /* enum */
- NULL, /* forward */
- tdtrav_plain, /* typedef */
- NULL, /* typedef_unres */
- tdtrav_plain, /* volatile */
- tdtrav_plain, /* const */
- tdtrav_plain /* restrict */
-};
-
-int
-tdtraverse(tdesc_t *this, tdesc_t **thisp, tdtrav_data_t *tdtd)
-{
- tdtrav_cb_f travcb;
- int (*descender)();
- int descend = 1;
- int rc;
-
- if ((travcb = tdtd->firstops[this->t_type]) != NULL) {
- if ((rc = travcb(this, thisp, tdtd->private)) < 0)
- return (rc);
- else if (rc == 0)
- descend = 0;
- }
-
- if (this->t_vgen == tdtd->vgen)
- return (1);
- this->t_vgen = tdtd->vgen;
-
- if (descend && (travcb = tdtd->preops[this->t_type]) != NULL) {
- if ((rc = travcb(this, thisp, tdtd->private)) < 0)
- return (rc);
- else if (rc == 0)
- descend = 0;
- }
-
- if (descend) {
- if ((descender = tddescenders[this->t_type]) != NULL &&
- (rc = descender(this, tdtd)) < 0)
- return (rc);
-
- if ((travcb = tdtd->postops[this->t_type]) != NULL &&
- (rc = travcb(this, thisp, tdtd->private)) < 0)
- return (rc);
- }
-
- return (1);
-}
-
-int
-iitraverse_td(iidesc_t *ii, tdtrav_data_t *tdtd)
-{
- int i, rc;
-
- if ((rc = tdtraverse(ii->ii_dtype, &ii->ii_dtype, tdtd)) < 0)
- return (rc);
-
- for (i = 0; i < ii->ii_nargs; i++) {
- if ((rc = tdtraverse(ii->ii_args[i], &ii->ii_args[i],
- tdtd)) < 0)
- return (rc);
- }
-
- return (1);
-}
-
-int
-iitraverse(iidesc_t *ii, int *vgenp, tdtrav_cb_f *firstops, tdtrav_cb_f *preops,
- tdtrav_cb_f *postops, void *private)
-{
- tdtrav_data_t tdtd;
-
- tdtrav_init(&tdtd, vgenp, firstops, preops, postops, private);
-
- return (iitraverse_td(ii, &tdtd));
-}
-
-int
-iitraverse_hash(hash_t *iihash, int *vgenp, tdtrav_cb_f *firstops,
- tdtrav_cb_f *preops, tdtrav_cb_f *postops, void *private)
-{
- tdtrav_data_t tdtd;
-
- tdtrav_init(&tdtd, vgenp, firstops, preops, postops, private);
-
- return (hash_iter(iihash, (int (*)())iitraverse_td, &tdtd));
-}
diff --git a/usr/src/tools/ctf/cvt/traverse.h b/usr/src/tools/ctf/cvt/traverse.h
deleted file mode 100644
index 0f8396f308..0000000000
--- a/usr/src/tools/ctf/cvt/traverse.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef _TRAVERSE_H
-#define _TRAVERSE_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Routines used to traverse tdesc trees, invoking user-supplied callbacks
- * as the tree is traversed.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "ctftools.h"
-
-typedef int (*tdtrav_cb_f)(tdesc_t *, tdesc_t **, void *);
-
-typedef struct tdtrav_data {
- int vgen;
-
- tdtrav_cb_f *firstops;
- tdtrav_cb_f *preops;
- tdtrav_cb_f *postops;
-
- void *private;
-} tdtrav_data_t;
-
-void tdtrav_init(tdtrav_data_t *, int *, tdtrav_cb_f *, tdtrav_cb_f *,
- tdtrav_cb_f *, void *);
-int tdtraverse(tdesc_t *, tdesc_t **, tdtrav_data_t *);
-
-int iitraverse(iidesc_t *, int *, tdtrav_cb_f *, tdtrav_cb_f *, tdtrav_cb_f *,
- void *);
-int iitraverse_hash(hash_t *, int *, tdtrav_cb_f *, tdtrav_cb_f *,
- tdtrav_cb_f *, void *);
-int iitraverse_td(iidesc_t *ii, tdtrav_data_t *);
-
-int tdtrav_assert(tdesc_t *, tdesc_t **, void *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _TRAVERSE_H */
diff --git a/usr/src/tools/ctf/cvt/util.c b/usr/src/tools/ctf/cvt/util.c
deleted file mode 100644
index 799ca1279c..0000000000
--- a/usr/src/tools/ctf/cvt/util.c
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * 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.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Utility functions
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <libelf.h>
-#include <gelf.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <sys/param.h>
-
-#include "ctftools.h"
-#include "memory.h"
-
-static void (*terminate_cleanup)() = NULL;
-
-/* returns 1 if s1 == s2, 0 otherwise */
-int
-streq(const char *s1, const char *s2)
-{
- if (s1 == NULL) {
- if (s2 != NULL)
- return (0);
- } else if (s2 == NULL)
- return (0);
- else if (strcmp(s1, s2) != 0)
- return (0);
-
- return (1);
-}
-
-int
-findelfsecidx(Elf *elf, const char *file, const char *tofind)
-{
- Elf_Scn *scn = NULL;
- GElf_Ehdr ehdr;
- GElf_Shdr shdr;
-
- if (gelf_getehdr(elf, &ehdr) == NULL)
- elfterminate(file, "Couldn't read ehdr");
-
- while ((scn = elf_nextscn(elf, scn)) != NULL) {
- char *name;
-
- if (gelf_getshdr(scn, &shdr) == NULL) {
- elfterminate(file,
- "Couldn't read header for section %d",
- elf_ndxscn(scn));
- }
-
- if ((name = elf_strptr(elf, ehdr.e_shstrndx,
- (size_t)shdr.sh_name)) == NULL) {
- elfterminate(file,
- "Couldn't get name for section %d",
- elf_ndxscn(scn));
- }
-
- if (strcmp(name, tofind) == 0)
- return (elf_ndxscn(scn));
- }
-
- return (-1);
-}
-
-size_t
-elf_ptrsz(Elf *elf)
-{
- GElf_Ehdr ehdr;
-
- if (gelf_getehdr(elf, &ehdr) == NULL) {
- terminate("failed to read ELF header: %s\n",
- elf_errmsg(-1));
- }
-
- if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
- return (4);
- else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64)
- return (8);
- else
- terminate("unknown ELF class %d\n", ehdr.e_ident[EI_CLASS]);
-
- /*NOTREACHED*/
- return (0);
-}
-
-/*PRINTFLIKE2*/
-static void
-whine(char *type, char *format, va_list ap)
-{
- int error = errno;
-
- fprintf(stderr, "%s: %s: ", type, progname);
- vfprintf(stderr, format, ap);
-
- if (format[strlen(format) - 1] != '\n')
- fprintf(stderr, ": %s\n", strerror(error));
-}
-
-void
-set_terminate_cleanup(void (*cleanup)())
-{
- terminate_cleanup = cleanup;
-}
-
-/*PRINTFLIKE1*/
-void
-terminate(char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- whine("ERROR", format, ap);
- va_end(ap);
-
- if (terminate_cleanup)
- terminate_cleanup();
-
- if (getenv("CTF_ABORT_ON_TERMINATE") != NULL)
- abort();
- exit(1);
-}
-
-/*PRINTFLIKE1*/
-void
-aborterr(char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- whine("ERROR", format, ap);
- va_end(ap);
-
- abort();
-}
-
-/*PRINTFLIKE1*/
-void
-warning(char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- whine("WARNING", format, ap);
- va_end(ap);
-
- if (debug_level >= 3)
- terminate("Termination due to warning\n");
-}
-
-/*PRINTFLIKE2*/
-void
-vadebug(int level, char *format, va_list ap)
-{
- if (level > debug_level)
- return;
-
- (void) fprintf(DEBUG_STREAM, "DEBUG: ");
- (void) vfprintf(DEBUG_STREAM, format, ap);
- fflush(DEBUG_STREAM);
-}
-
-/*PRINTFLIKE2*/
-void
-debug(int level, char *format, ...)
-{
- va_list ap;
-
- if (level > debug_level)
- return;
-
- va_start(ap, format);
- (void) vadebug(level, format, ap);
- va_end(ap);
-}
-
-char *
-mktmpname(const char *origname, const char *suffix)
-{
- char *newname;
-
- newname = xmalloc(strlen(origname) + strlen(suffix) + 1);
- (void) strcpy(newname, origname);
- (void) strcat(newname, suffix);
- return (newname);
-}
-
-/*PRINTFLIKE2*/
-void
-elfterminate(const char *file, const char *fmt, ...)
-{
- static char msgbuf[BUFSIZ];
- va_list ap;
-
- va_start(ap, fmt);
- vsnprintf(msgbuf, sizeof (msgbuf), fmt, ap);
- va_end(ap);
-
- terminate("%s: %s: %s\n", file, msgbuf, elf_errmsg(-1));
-}
-
-const char *
-tdesc_name(tdesc_t *tdp)
-{
- return (tdp->t_name == NULL ? "(anon)" : tdp->t_name);
-}