OpenSolaris Launch
diff --git a/usr/src/cmd/Adm/.proto b/usr/src/cmd/Adm/.proto
new file mode 100644
index 0000000..2e3929d
--- /dev/null
+++ b/usr/src/cmd/Adm/.proto
@@ -0,0 +1,28 @@
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# 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
+#
+#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.2 */
+cd $d
+umask $m
+$<
diff --git a/usr/src/cmd/Adm/Makefile b/usr/src/cmd/Adm/Makefile
new file mode 100644
index 0000000..571fdc9
--- /dev/null
+++ b/usr/src/cmd/Adm/Makefile
@@ -0,0 +1,91 @@
+#
+# 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 2003 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+CRON_ENT= adm root sys
+CRON_LIB= .proto at.deny cron.deny queuedefs
+ETC_SCRIPT= group project ttysrch
+ZI_SPECIAL= zones-index
+SUBDIRS= sun
+
+include ../Makefile.cmd
+
+all:= TARGET= all
+install:= TARGET= install
+clean:= TARGET= clean
+clobber:= TARGET= clobber
+lint:= TARGET= lint
+
+CROND= $(ROOT)/var/spool/cron
+CRONTABD= $(ROOT)/var/spool/cron/crontabs
+CRONLIBD= $(ROOT)/etc/cron.d
+ETCZONESD= $(ROOT)/etc/zones
+DIRS= $(CROND) $(CRONTABD) $(CRONLIBD)
+
+CRONTABS= $(CRON_ENT:%=$(CRONTABD)/%)
+CRONLIBS= $(CRON_LIB:%=$(CRONLIBD)/%)
+ETCSCRIPTS= $(ETC_SCRIPT:%=$(ROOTETC)/%)
+ZISPECIALS= $(ETCZONESD)/index
+
+FILEMODE= 0644
+GROUP= sys
+
+$(CRONLIBD)/.proto := FILEMODE = 0744
+$(CRONTABD)/adm := FILEMODE = 0600
+$(CRONTABD)/sys := FILEMODE = 0600
+$(CRONTABD)/root := FILEMODE = 0600
+
+.KEEP_STATE:
+
+all: $(CRON_ENT) $(CRON_LIB) $(ETC_SCRIPT) $(SUBDIRS)
+
+install: all $(DIRS) $(CRONTABS) $(CRONLIBS) $(ETCSCRIPTS) $(ETCZONESD) \
+ $(SUBDIRS)
+
+$(CRONTABD)/% : %
+ $(INS.file)
+
+$(CRONLIBD)/% : %
+ $(INS.file)
+
+$(ETCZONESD): $(ZI_SPECIAL)
+ $(CP) -f $(ZI_SPECIAL) $(ZISPECIALS)
+ $(CHMOD) $(FILEMODE) $(ZISPECIALS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(MFLAGS) $(TARGET)
+
+$(DIRS):
+ $(INS.dir)
+
+FRC:
+
+clean:
+
+lint:
+
+clobber:
diff --git a/usr/src/cmd/Adm/adm b/usr/src/cmd/Adm/adm
new file mode 100644
index 0000000..7b87b41
--- /dev/null
+++ b/usr/src/cmd/Adm/adm
@@ -0,0 +1,26 @@
+#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.2 */
+#
+# 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
+#
+#
+# The adm crontab file should contain startup of performance collection if
+# the profiling and performance feature has been installed.
+#
diff --git a/usr/src/cmd/Adm/at.deny b/usr/src/cmd/Adm/at.deny
new file mode 100644
index 0000000..dda982d
--- /dev/null
+++ b/usr/src/cmd/Adm/at.deny
@@ -0,0 +1,3 @@
+daemon
+bin
+nuucp
diff --git a/usr/src/cmd/Adm/cron.deny b/usr/src/cmd/Adm/cron.deny
new file mode 100644
index 0000000..dda982d
--- /dev/null
+++ b/usr/src/cmd/Adm/cron.deny
@@ -0,0 +1,3 @@
+daemon
+bin
+nuucp
diff --git a/usr/src/cmd/Adm/group b/usr/src/cmd/Adm/group
new file mode 100644
index 0000000..20e9789
--- /dev/null
+++ b/usr/src/cmd/Adm/group
@@ -0,0 +1,19 @@
+root::0:
+other::1:root
+bin::2:root,daemon
+sys::3:root,bin,adm
+adm::4:root,daemon
+uucp::5:root
+mail::6:root
+tty::7:root,adm
+lp::8:root,adm
+nuucp::9:root
+staff::10:
+daemon::12:root
+sysadmin::14:
+smmsp::25:
+gdm::50:
+webservd::80:
+nobody::60001:
+noaccess::60002:
+nogroup::65534:
diff --git a/usr/src/cmd/Adm/project b/usr/src/cmd/Adm/project
new file mode 100644
index 0000000..615f5de
--- /dev/null
+++ b/usr/src/cmd/Adm/project
@@ -0,0 +1,5 @@
+system:0::::
+user.root:1::::
+noproject:2::::
+default:3::::
+group.staff:10::::
diff --git a/usr/src/cmd/Adm/queuedefs b/usr/src/cmd/Adm/queuedefs
new file mode 100644
index 0000000..05c95b0
--- /dev/null
+++ b/usr/src/cmd/Adm/queuedefs
@@ -0,0 +1,2 @@
+a.4j1n
+b.2j2n90w
diff --git a/usr/src/cmd/Adm/root b/usr/src/cmd/Adm/root
new file mode 100644
index 0000000..aaa964d
--- /dev/null
+++ b/usr/src/cmd/Adm/root
@@ -0,0 +1,32 @@
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# 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
+#
+#
+# The root crontab should be used to perform accounting data collection.
+#
+#
+10 3 * * * /usr/sbin/logadm
+15 3 * * 0 /usr/lib/fs/nfs/nfsfind
+30 3 * * * [ -x /usr/lib/gss/gsscred_clean ] && /usr/lib/gss/gsscred_clean
diff --git a/usr/src/cmd/Adm/sun/Makefile b/usr/src/cmd/Adm/sun/Makefile
new file mode 100644
index 0000000..017f4ff
--- /dev/null
+++ b/usr/src/cmd/Adm/sun/Makefile
@@ -0,0 +1,69 @@
+#
+# 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
+#
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1989, 1995, 1997 by Sun Microsystems, Inc.
+# All Rights Reserved
+#
+
+ETCFILES= ioctl.syscon passwd shadow motd
+KVMFILES= README
+
+include ../../Makefile.cmd
+
+ROOTETCFILES= $(ETCFILES:%=$(ROOTETC)/%)
+ROOTUSRKVMFILES= $(KVMFILES:%=$(ROOTUSRKVM)/%)
+
+FILEMODE= 0644
+OWNER= root
+GROUP= sys
+
+$(ROOTETC)/shadow := FILEMODE = 400
+
+.KEEP_STATE:
+
+all: $(ETCFILES) $(KVMFILES)
+
+install: all $(ROOTETCFILES) $(ROOTUSRKVMFILES)
+
+clean:
+
+lint:
+
+clobber:
+
+motd: FRC
+ @-$(ECHO) "rebuilding motd"
+ @$(RELEASE_BUILD)-$(ECHO) "Sun Microsystems Inc.\tSunOS $(RELEASE)\t$(VERSION)\t$(RELEASE_DATE)" > motd
+ @$(NOT_RELEASE_BUILD)-$(ECHO) "Sun Microsystems Inc.\tSunOS $(RELEASE)\t$(VERSION)\t`date +'%h. %d, %Y'`" > motd
+ @$(NOT_RELEASE_BUILD)-$(ECHO) $(DEV_CM) | sed -e "s/@(#)//" >> motd
+ @-$(CAT) release_info >> motd
+
+clean:
+
+lint:
+
+clobber:
+ $(RM) motd
+
+FRC:
diff --git a/usr/src/cmd/Adm/sun/README b/usr/src/cmd/Adm/sun/README
new file mode 100644
index 0000000..f333944
--- /dev/null
+++ b/usr/src/cmd/Adm/sun/README
@@ -0,0 +1,87 @@
+#
+# 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
+#
+
+Elimination of /usr/kvm
+=======================
+
+Copyright (c) 1995-2000 by Sun Microsystems, Inc.
+All rights reserved.
+
+#ident "%Z%%M% %I% %E% SMI"
+
+As of Solaris 2.5, the /usr/kvm directory is no longer needed by the
+operating environment. The mount point continues to be provided for
+backward compatibility although all of the contents have been removed.
+
+In earlier releases, /usr/kvm contained the platform specific implementations
+of programs and libraries. The interface to these platform specific
+implementations was generally advertized to be in a platform independent
+directory and a symbolic link was used to bind the advertized platform
+independent interface to the platform specific implementation in /usr/kvm.
+
+Implementation Interface(s)
+
+/usr/kvm/adb /usr/bin/adb
+
+/usr/kvm/arch /usr/ucb/arch
+
+ Note: Source Compatibility Package Component
+
+/usr/kvm/crash /usr/bin/mdb
+
+ Note: Solaris Modular Debugger Guide describes how to
+ transition from crash(1M) to mdb(1).
+
+/usr/kvm/eeprom /usr/sbin/eeprom
+
+/usr/kvm/i286,i386,i486,i860,i86pc,iAPX286,m68k,mc68000,mc68010,mc68020,
+ mc68030,mc68040,sparc,sun,sun2,sun3,sun3x,sun4,sun4c,sun4d,sun4e,
+ sun4m,u370,u3b,u3b15,u3b2,u3b5,vax
+ /usr/bin/i286,i386,i486,i860,i86pc,iAPX286,m68k,
+ mc68000,mc68010,mc68020,mc68030,mc68040,sparc,sun,
+ sun2,sun3,sun3x,sun4,sun4c,sun4d,sun4e,sun4m,u370,
+ u3b,u3b15,u3b2,u3b5,vax
+
+ Note: These are documented on the machid(1) manual
+ page. These are fully deprecated interfaces.
+
+/usr/kvm/libkvm.a /usr/lib/libkvm.a
+
+ Note: /usr/lib/libkvm.a is no longer a component
+ of SunOS.
+
+/usr/kvm/libkvm.so.1 /usr/lib/libkvm.so.1
+/usr/kvm/libkvm.so /usr/lib/libkvm.so
+
+
+The following platform specific objects were also delivered in previous
+releases of SunOS. They are only of use with specific platforms and
+it was always documented that the path to these objects was uncommitted.
+
+2.4 (and earlier) 2.5
+
+/usr/kvm/cg14config /usr/platform/sun4m/sbin/cg14config sun4m only
+
+/usr/kvm/sxconfig /usr/platform/sun4m/sbin/sxconfig sun4m only
+
+/usr/kvm/prtdiag /usr/platform/sun4d/sbin/prtdiag sun4d only
+
diff --git a/usr/src/cmd/Adm/sun/ioctl.syscon b/usr/src/cmd/Adm/sun/ioctl.syscon
new file mode 100644
index 0000000..bf38cc8
--- /dev/null
+++ b/usr/src/cmd/Adm/sun/ioctl.syscon
@@ -0,0 +1 @@
+2502:1805:bd:8a3b:0:3:1c:7f:15:4:0:0:0
diff --git a/usr/src/cmd/Adm/sun/passwd b/usr/src/cmd/Adm/sun/passwd
new file mode 100644
index 0000000..588dbd6
--- /dev/null
+++ b/usr/src/cmd/Adm/sun/passwd
@@ -0,0 +1,15 @@
+root:x:0:0:Super-User:/:/sbin/sh
+daemon:x:1:1::/:
+bin:x:2:2::/usr/bin:
+sys:x:3:3::/:
+adm:x:4:4:Admin:/var/adm:
+lp:x:71:8:Line Printer Admin:/usr/spool/lp:
+uucp:x:5:5:uucp Admin:/usr/lib/uucp:
+nuucp:x:9:9:uucp Admin:/var/spool/uucppublic:/usr/lib/uucp/uucico
+smmsp:x:25:25:SendMail Message Submission Program:/:
+listen:x:37:4:Network Admin:/usr/net/nls:
+gdm:x:50:50:GDM Reserved UID:/:
+webservd:x:80:80:WebServer Reserved UID:/:
+nobody:x:60001:60001:NFS Anonymous Access User:/:
+noaccess:x:60002:60002:No Access User:/:
+nobody4:x:65534:65534:SunOS 4.x NFS Anonymous Access User:/:
diff --git a/usr/src/cmd/Adm/sun/release_info b/usr/src/cmd/Adm/sun/release_info
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/usr/src/cmd/Adm/sun/release_info
diff --git a/usr/src/cmd/Adm/sun/shadow b/usr/src/cmd/Adm/sun/shadow
new file mode 100644
index 0000000..8c2c3de
--- /dev/null
+++ b/usr/src/cmd/Adm/sun/shadow
@@ -0,0 +1,15 @@
+root::6445::::::
+daemon:NP:6445::::::
+bin:NP:6445::::::
+sys:NP:6445::::::
+adm:NP:6445::::::
+lp:NP:6445::::::
+uucp:NP:6445::::::
+nuucp:NP:6445::::::
+smmsp:NP:6445::::::
+listen:*LK*:::::::
+gdm:*LK*:::::::
+webservd:*LK*:::::::
+nobody:*LK*:6445::::::
+noaccess:*LK*:6445::::::
+nobody4:*LK*:6445::::::
diff --git a/usr/src/cmd/Adm/sys b/usr/src/cmd/Adm/sys
new file mode 100644
index 0000000..c258c7d
--- /dev/null
+++ b/usr/src/cmd/Adm/sys
@@ -0,0 +1,26 @@
+#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.2 */
+#
+# 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
+#
+#
+# The sys crontab should be used to do performance collection. See cron
+# and performance manual pages for details on startup.
+#
diff --git a/usr/src/cmd/Adm/ttysrch b/usr/src/cmd/Adm/ttysrch
new file mode 100644
index 0000000..ef3bd2e
--- /dev/null
+++ b/usr/src/cmd/Adm/ttysrch
@@ -0,0 +1,60 @@
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# 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
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# This file is used by ttyname(3C) to minimize search time
+# during attempts to determine the name of a terminal device.
+#
+# This is done by providing the names of directories which
+# are most likely to contain device entries for terminal
+# devices. These directories will be searched in the order
+# listed prior to an exhaustive search of the rest of /dev.
+#
+# Each line contains the name of a directory (which must
+# begin with "/dev") and (optionally) a set of flags which
+# modify the criteria used to determine a match. By default,
+# an exact match requires that the major/minor device number
+# (the M flag), the file system identifier (the F flag), and
+# the inode number (the I flag) all match. Normally, a partial
+# match on the major/minor device and the file system identifier
+# is accepted only after exhausting all entries under /dev.
+# By specifying only the M and F flags, an exact match will
+# be accepted regardless of the value of the inode number as
+# soon as it is found. This is especially useful for cloned
+# devices, which generally will not match inode numbers.
+#
+# For additional information see ttysrch(4).
+#
+# EXAMPLE:
+#
+# /dev/slan MF
+#
+# This would improve performance for Starlan network connections
+# if all Starlan network clone device entries were contained
+# in the /dev/slan directory.
+#
+/dev/pts
+/dev/term
+/dev/zcons
diff --git a/usr/src/cmd/Adm/zones-index b/usr/src/cmd/Adm/zones-index
new file mode 100644
index 0000000..91fe7a9
--- /dev/null
+++ b/usr/src/cmd/Adm/zones-index
@@ -0,0 +1,29 @@
+# ident "%Z%%M% %I% %E% SMI"
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# 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
+#
+#
+# DO NOT EDIT: this file is automatically generated by zoneadm(1M)
+# and zonecfg(1M). Any manual changes will be lost.
+#
+global:installed:/
diff --git a/usr/src/cmd/Makefile b/usr/src/cmd/Makefile
new file mode 100644
index 0000000..5b89a04
--- /dev/null
+++ b/usr/src/cmd/Makefile
@@ -0,0 +1,832 @@
+#
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.master
+
+#
+# Note that the commands 'agents', 'lp', 'perl', and 'man' are first in
+# the list, violating alphabetical order. This is because they are very
+# long-running and should be given the most wall-clock time for a
+# parallel build.
+#
+# Commands in the FIRST_SUBDIRS list are built before starting the build
+# of other commands. Currently this includes only 'isaexec' and
+# 'platexec'. This is necessary because $(ROOT)/usr/lib/isaexec or
+# $(ROOT)/usr/lib/platexec must exist when some other commands are built
+# because their 'make install' creates a hard link to one of them.
+#
+# Commands are listed one per line so that TeamWare can auto-merge most
+# changes.
+#
+
+FIRST_SUBDIRS= \
+ isaexec \
+ platexec
+
+COMMON_SUBDIRS= \
+ agents \
+ lp \
+ perl \
+ man \
+ Adm \
+ abi \
+ adbgen \
+ acct \
+ acctadm \
+ arch \
+ asa \
+ aset \
+ audio \
+ auths \
+ autopush \
+ awk \
+ awk_xpg4 \
+ backup \
+ banner \
+ bart \
+ basename \
+ bc \
+ bdiff \
+ bfs \
+ bnu \
+ boot \
+ busstat \
+ cal \
+ calendar \
+ captoinfo \
+ cat \
+ cdrw \
+ cfgadm \
+ checkeq \
+ checknr \
+ chgrp \
+ chmod \
+ chown \
+ chroot \
+ cksum \
+ clear \
+ clinfo \
+ cmd-crypto \
+ cmd-inet \
+ cmp \
+ col \
+ comm \
+ compress \
+ consadm \
+ coreadm \
+ cpio \
+ cpc \
+ cron \
+ crypt \
+ csh \
+ csplit \
+ ctrun \
+ ctstat \
+ ctwatch \
+ cut \
+ datadm \
+ date \
+ dc \
+ dd \
+ deroff \
+ des \
+ devfsadm \
+ syseventd \
+ devctl \
+ devinfo \
+ devmgmt \
+ dfs.cmds \
+ diff \
+ diff3 \
+ diffmk \
+ dircmp \
+ dirname \
+ diskmgtd \
+ dispadmin \
+ dladm \
+ dmesg \
+ dodatadm \
+ dtrace \
+ du \
+ dumpadm \
+ dumpcs \
+ echo \
+ ed \
+ eeprom \
+ egrep \
+ enhance \
+ env \
+ eqn \
+ expand \
+ expr \
+ exstr \
+ face \
+ factor \
+ false \
+ fdetach \
+ fdformat \
+ fdisk \
+ filesync \
+ fgrep \
+ file \
+ find \
+ fm \
+ fmli \
+ fmt \
+ fmthard \
+ fmtmsg \
+ fold \
+ format \
+ fs.d \
+ fstyp \
+ fuser \
+ gcore \
+ gencat \
+ geniconvtbl \
+ genmsg \
+ getconf \
+ getdevpolicy \
+ getent \
+ getfacl \
+ getmajor \
+ getopt \
+ gettext \
+ gettxt \
+ graph \
+ grep \
+ grep_xpg4 \
+ groups \
+ grpck \
+ gss \
+ halt \
+ head \
+ hostid \
+ hostname \
+ iconv \
+ id \
+ infocmp \
+ init \
+ initpkg \
+ install.d \
+ intrstat \
+ ipcrm \
+ ipcs \
+ ipf \
+ isainfo \
+ isalist \
+ java \
+ join \
+ kbd \
+ keyserv \
+ killall \
+ krb5 \
+ ksh \
+ kstat \
+ last \
+ lastcomm \
+ ldap \
+ ldapcachemgr \
+ line \
+ link \
+ listen \
+ llc2 \
+ loadkeys \
+ locale \
+ localedef \
+ lockstat \
+ locator \
+ lofiadm \
+ logadm \
+ logger \
+ login \
+ logins \
+ logname \
+ look \
+ ls \
+ lvm \
+ mach \
+ machid \
+ mail \
+ mailx \
+ makekey \
+ mdb \
+ mesg \
+ mkdir \
+ mkfifo \
+ mkfile \
+ mkmsgs \
+ mknod \
+ mkpwdict \
+ mktemp \
+ modload \
+ more \
+ more_xpg4 \
+ msgfmt \
+ msgid \
+ mt \
+ mv \
+ mvdir \
+ netadm \
+ netfiles \
+ newform \
+ newgrp \
+ news \
+ newtask \
+ nice \
+ nispasswd \
+ nl \
+ nlsadmin \
+ nohup \
+ nsadmin \
+ nscd \
+ oamuser \
+ oawk \
+ od \
+ openssl \
+ pack \
+ pagesize \
+ passmgmt \
+ passwd \
+ paste \
+ patch \
+ pathchk \
+ pax \
+ pbind \
+ pcitool \
+ pcmciad \
+ pfexec \
+ pgrep \
+ picl \
+ plimit \
+ pools \
+ power \
+ ppgsz \
+ pg \
+ plockstat \
+ pr \
+ prctl \
+ print \
+ printf \
+ priocntl \
+ profiles \
+ projadd \
+ projects \
+ prstat \
+ prtconf \
+ prtdiag \
+ prtvtoc \
+ ps \
+ psradm \
+ psrinfo \
+ psrset \
+ pt_chmod \
+ ptools \
+ pwck \
+ pwconv \
+ pwd \
+ raidctl \
+ ramdiskadm \
+ rcap \
+ rcm_daemon \
+ rctladm \
+ refer \
+ regcmp \
+ renice \
+ rexd \
+ rm \
+ rmdir \
+ rmformat \
+ rmt \
+ roles \
+ rpcbind \
+ rpcgen \
+ rpcinfo \
+ rpcsvc \
+ rpld \
+ runat \
+ sa \
+ saf \
+ savecore \
+ script \
+ sdiff \
+ sed \
+ sed_xpg4 \
+ sendmail \
+ setfacl \
+ setmnt \
+ setpgrp \
+ setuname \
+ sgs \
+ sh \
+ sleep \
+ smartcard \
+ smserverd \
+ soelim \
+ sort \
+ spell \
+ spline \
+ split \
+ srchtxt \
+ ssh \
+ stat \
+ streams \
+ strings \
+ su \
+ sulogin \
+ sum \
+ sunpc \
+ svc \
+ swap \
+ sync \
+ sysdef \
+ syseventadm \
+ syslogd \
+ tabs \
+ tail \
+ tar \
+ tbl \
+ tcopy \
+ tcpd \
+ tee \
+ terminfo \
+ th_tools \
+ tic \
+ time \
+ tip \
+ tnf \
+ touch \
+ tplot \
+ tput \
+ tr \
+ tr_xpg4 \
+ trapstat \
+ troff \
+ true \
+ truss \
+ tty \
+ ttymon \
+ uadmin \
+ ul \
+ uname \
+ uniq \
+ units \
+ unlink \
+ unpack \
+ users \
+ utmp_update \
+ utmpd \
+ valtools \
+ vgrind \
+ vi \
+ volmgt \
+ w \
+ wall \
+ wbem \
+ wc \
+ which \
+ who \
+ whodo \
+ wracct \
+ write \
+ xntpd \
+ xargs \
+ xstr \
+ yes \
+ ypcmd \
+ yppasswd \
+ zdump \
+ zic \
+ zlogin \
+ zoneadm \
+ zoneadmd \
+ zonecfg \
+ zonename
+
+i386_SUBDIRS= \
+ addbadsec \
+ biosdev \
+ diskscan \
+ OWconfig \
+ rtc
+
+sparc_SUBDIRS= \
+ cvcd \
+ dcs \
+ fruadm \
+ mtst \
+ prtfru \
+ scadm \
+ sckmd \
+ sf880drd \
+ stmsboot \
+ wrsmconf \
+ wrsmstat
+
+#
+# Commands that are messaged. Note that 'lp' and 'man' come first
+# (see previous comment about 'lp' and 'man').
+#
+MSGSUBDIRS= \
+ lp \
+ man \
+ abi \
+ acctadm \
+ allocate \
+ asa \
+ audio \
+ audit \
+ auditd \
+ auths \
+ autopush \
+ awk \
+ awk_xpg4 \
+ backup \
+ banner \
+ bart \
+ basename \
+ bnu \
+ bsmconv \
+ bsmrecord \
+ bsmunconv \
+ busstat \
+ cal \
+ cat \
+ cdrw \
+ cfgadm \
+ checkeq \
+ checknr \
+ chgrp \
+ chmod \
+ chown \
+ cksum \
+ cmd-crypto \
+ cmd-inet \
+ cmp \
+ col \
+ comm \
+ compress \
+ consadm \
+ coreadm \
+ cpio \
+ cpc \
+ cron \
+ csh \
+ csplit \
+ ctrun \
+ ctstat \
+ ctwatch \
+ cut \
+ datadm \
+ date \
+ dc \
+ dcs \
+ dd \
+ deroff \
+ devfsadm \
+ diff \
+ diffmk \
+ dladm \
+ du \
+ dumpcs \
+ ed \
+ env \
+ eqn \
+ expand \
+ expr \
+ fgrep \
+ file \
+ filesync \
+ find \
+ fm \
+ fold \
+ fs.d \
+ geniconvtbl \
+ genmsg \
+ getconf \
+ getent \
+ gettext \
+ gettxt \
+ grep \
+ grep_xpg4 \
+ grpck \
+ gss \
+ halt \
+ head \
+ hostname \
+ iconv \
+ id \
+ isaexec \
+ join \
+ krb5 \
+ ksh \
+ kstat \
+ last \
+ ldap \
+ ldapcachemgr \
+ llc2 \
+ locale \
+ localedef \
+ lofiadm \
+ logadm \
+ logger \
+ logins \
+ logname \
+ ls \
+ lvm \
+ mailx \
+ mesg \
+ mkdir \
+ mkpwdict \
+ mktemp \
+ more \
+ more_xpg4 \
+ msgfmt \
+ mv \
+ newgrp \
+ newtask \
+ nice \
+ nispasswd \
+ nohup \
+ oawk \
+ od \
+ pack \
+ passwd \
+ passmgmt \
+ paste \
+ patch \
+ pathchk \
+ pax \
+ pfexec \
+ pg \
+ pgrep \
+ picl \
+ pools \
+ power \
+ pr \
+ praudit \
+ print \
+ printf \
+ profiles \
+ projadd \
+ projects \
+ prstat \
+ prtdiag \
+ ps \
+ psrinfo \
+ pwconv \
+ pwd \
+ raidctl \
+ ramdiskadm \
+ rcap \
+ rcm_daemon \
+ refer \
+ regcmp \
+ renice \
+ roles \
+ rm \
+ rmdir \
+ rmformat \
+ scadm \
+ script \
+ sdiff \
+ sed \
+ sed_xpg4 \
+ sgs \
+ sh \
+ sleep \
+ sort \
+ split \
+ ssh \
+ strings \
+ su \
+ sum \
+ svc \
+ swap \
+ syseventadm \
+ syseventd \
+ tabs \
+ tail \
+ tar \
+ tbl \
+ tee \
+ time \
+ tnf \
+ touch \
+ tput \
+ tr \
+ tr_xpg4 \
+ troff \
+ tty \
+ ttymon \
+ ul \
+ uname \
+ uniq \
+ units \
+ unlink \
+ unpack \
+ valtools \
+ vgrind \
+ vi \
+ volmgt \
+ w \
+ wbem \
+ wc \
+ who \
+ whodo \
+ wracct \
+ write \
+ xargs \
+ yppasswd \
+ zdump \
+ zic \
+ zlogin \
+ zoneadm \
+ zoneadmd \
+ zonecfg \
+ zonename
+
+sparc_MSGSUBDIRS= \
+ fruadm \
+ prtfru \
+ stmsboot \
+ wrsmconf \
+ wrsmstat
+
+#
+# commands that use dcgettext for localized time, LC_TIME
+#
+DCSUBDIRS= \
+ cal \
+ cfgadm \
+ diff \
+ ls \
+ pax \
+ pr \
+ tar \
+ w \
+ who \
+ whodo \
+ write
+
+#
+# commands that belong only to the basic security module
+#
+BSMSUBDIRS= \
+ allocate \
+ amt \
+ audit \
+ audit_warn \
+ auditconfig \
+ auditd \
+ auditreduce \
+ auditstat \
+ dminfo \
+ praudit \
+ bsmconv \
+ bsmrecord \
+ bsmunconv
+
+#
+# commands not owned by the systems group
+#
+BWOSDIRS=
+
+#
+# Commands providing manifests must offer a check target. A recursive check
+# target across all commands directories is not currently provided.
+#
+MANIFEST_TOPDIRS= \
+ auditd \
+ bnu \
+ consadm \
+ coreadm \
+ cron \
+ cvcd \
+ dumpadm \
+ eeprom \
+ fm \
+ ipf \
+ keyserv \
+ ldapcachemgr \
+ nscd \
+ power \
+ rexd \
+ rpcbind \
+ rpcsvc \
+ saf \
+ sf880drd \
+ smserverd \
+ syseventd \
+ syslogd \
+ utmpd \
+ ypcmd \
+ zoneadmd
+
+MANIFEST_SUBDIRS= \
+ cmd-crypto/scripts \
+ cmd-inet/usr.lib/in.chargend \
+ cmd-inet/usr.lib/in.daytimed \
+ cmd-inet/usr.lib/in.dhcpd \
+ cmd-inet/usr.lib/in.discardd \
+ cmd-inet/usr.lib/in.echod \
+ cmd-inet/usr.lib/in.timed \
+ cmd-inet/usr.lib/inetd \
+ cmd-inet/usr.lib/slpd \
+ cmd-inet/usr.sbin \
+ cmd-inet/usr.sbin/in.ftpd \
+ cmd-inet/usr.sbin/in.talkd \
+ dcs/sparc/sun4u \
+ fs.d/autofs \
+ fs.d/cachefs \
+ fs.d/nfs/svc \
+ gss/gssd \
+ krb5/kadmin/server \
+ krb5/krb5kdc \
+ krb5/kwarn \
+ krb5/slave \
+ lp/cmd/lpsched \
+ lvm/rpc.metad \
+ lvm/rpc.metamedd \
+ lvm/rpc.metamhd \
+ lvm/md_monitord \
+ lvm/metassist/sysfiles \
+ lvm/util \
+ picl/picld \
+ print/gateway \
+ print/lp \
+ rcap/rcapd \
+ rpcsvc/rpc.bootparamd \
+ sendmail/lib \
+ smartcard/daemon \
+ ssh/etc \
+ svc/milestone \
+ ypcmd/yppasswd \
+ ypcmd/ypupdated \
+ xntpd/xntpd
+
+all := TARGET = all
+install := TARGET = install
+clean := TARGET = clean
+clobber := TARGET = clobber
+lint := TARGET = lint
+check := TARGET = check
+_msg := TARGET = _msg
+_dc := TARGET = _dc
+
+.KEEP_STATE:
+
+SUBDIRS = $(COMMON_SUBDIRS) $($(MACH)_SUBDIRS)
+
+.PARALLEL: $(BWOSDIRS) $(SUBDIRS) $(MSGSUBDIRS) $(BSMSUBDIRS) \
+ $(MANIFEST_SUBDIRS)
+
+all install clean clobber lint: $(FIRST_SUBDIRS) .WAIT $(SUBDIRS) $(BSMSUBDIRS)
+
+check: svccfg_check .WAIT $(MANIFEST_TOPDIRS) $(MANIFEST_SUBDIRS)
+
+svccfg_check:
+ @$(ECHO) "building requirements for svccfg check ..."; \
+ (cd $(SRC)/cmd/svc/svccfg && pwd && $(MAKE) $(MFLAGS) native)
+
+#
+# The .WAIT directive works around an apparent bug in parallel make.
+# Evidently make was getting the target _msg vs. _dc confused under
+# some level of parallelization, causing some of the _dc objects
+# not to be built.
+#
+_msg: $(MSGSUBDIRS) $($(MACH)_MSGSUBDIRS) .WAIT _dc
+
+_dc: $(DCSUBDIRS)
+
+$(FIRST_SUBDIRS) $(BWOSDIRS) $(SUBDIRS) $(BSMSUBDIRS) $(MANIFEST_SUBDIRS): FRC
+ @if [ -f $@/Makefile ]; then \
+ cd $@; pwd; $(MAKE) $(TARGET); \
+ else \
+ true; \
+ fi
+
+FRC:
diff --git a/usr/src/cmd/Makefile.cmd b/usr/src/cmd/Makefile.cmd
new file mode 100644
index 0000000..1d074eb
--- /dev/null
+++ b/usr/src/cmd/Makefile.cmd
@@ -0,0 +1,419 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# Definitions common to command source.
+#
+# include global definitions; SRC should be defined in the shell.
+# SRC is needed until RFE 1026993 is implemented.
+
+include $(SRC)/Makefile.master
+
+LN= ln
+CP= cp
+SH= sh
+ECHO= echo
+MKDIR= mkdir
+TOUCH= touch
+
+FILEMODE= 0555
+LIBFILEMODE= 0444
+XPG4= $(XPG4PROG:%=%.xpg4)
+XPG6= $(XPG6PROG:%=%.xpg6)
+
+KRB5DIR= $(ROOT)/usr
+KRB5BIN= $(KRB5DIR)/bin
+KRB5SBIN= $(KRB5DIR)/sbin
+KRB5LIB= $(KRB5DIR)/lib/krb5
+KRB5RUNPATH= /usr/lib/krb5
+GSSRUNPATH= /usr/lib/gss
+
+
+ROOTBIN= $(ROOT)/usr/bin
+ROOTLIB= $(ROOT)/usr/lib
+ROOTLIBSVCBIN= $(ROOT)/lib/svc/bin
+ROOTLIBSVCMETHOD= $(ROOT)/lib/svc/method
+
+ROOTSHLIB= $(ROOT)/usr/share/lib
+ROOTSBIN= $(ROOT)/sbin
+ROOTUSRSBIN= $(ROOT)/usr/sbin
+ROOTETC= $(ROOT)/etc
+ROOTCCSBIN= $(ROOT)/usr/ccs/bin
+ROOTUSRKVM= $(ROOT)/usr/kvm
+ROOTXPG4= $(ROOT)/usr/xpg4
+ROOTXPG4BIN= $(ROOT)/usr/xpg4/bin
+ROOTXPG4BIN32= $(ROOTXPG4BIN)/$(MACH32)
+ROOTXPG4BIN64= $(ROOTXPG4BIN)/$(MACH64)
+ROOTXPG6= $(ROOT)/usr/xpg6
+ROOTXPG6BIN= $(ROOT)/usr/xpg6/bin
+ROOTLOCALEDEF= $(ROOT)/usr/lib/localedef
+ROOTCHARMAP= $(ROOTLOCALEDEF)/charmap
+ROOTI18NEXT= $(ROOTLOCALEDEF)/extensions
+ROOTI18NEXT64= $(ROOTLOCALEDEF)/extensions/$(MACH64)
+ROOTBIN32= $(ROOTBIN)/$(MACH32)
+ROOTBIN64= $(ROOTBIN)/$(MACH64)
+ROOTCMDDIR64= $(ROOTCMDDIR)/$(MACH64)
+ROOTLIB64= $(ROOTLIB)/$(MACH64)
+ROOTUSRSBIN32= $(ROOTUSRSBIN)/$(MACH32)
+ROOTUSRSBIN64= $(ROOTUSRSBIN)/$(MACH64)
+ROOTMAN1= $(ROOT)/usr/share/man/man1
+ROOTMAN1M= $(ROOT)/usr/share/man/man1m
+ROOTMAN3= $(ROOT)/usr/share/man/man3
+
+#
+
+# Like ROOTLIBDIR in $(SRC)/Makefile.lib, any lower-level Makefiles that
+# put their binaries in a non-standard location should reset this and use
+# $(ROOTCMD) in their `install' target. By default we set this to a bogus
+# value so that it will not conflict with any of the other values already
+# defined in this Makefile.
+#
+ROOTCMDDIR= $(ROOT)/__nonexistent_directory__
+
+ROOTSHAUDIO= $(ROOT)/usr/share/audio
+ROOTAUDIOSAMP= $(ROOTSHAUDIO)/samples
+ROOTAUDIOSAMPAU=$(ROOTAUDIOSAMP)/au
+
+#
+# Begin /usr/sfw freeware rules for freeware that has "External"
+# taxonomy stability level.
+#
+ROOTSFW= $(ROOT)/usr/sfw
+ROOTSFWBIN= $(ROOT)/usr/sfw/bin
+ROOTSFWSBIN= $(ROOT)/usr/sfw/sbin
+ROOTSFWSHARE= $(ROOT)/usr/sfw/share
+ROOTSFWSHSRC= $(ROOT)/usr/sfw/share/src
+ROOTSFWINFO= $(ROOT)/usr/sfw/share/info
+ROOTSFWINCLUDE= $(ROOT)/usr/sfw/include
+ROOTSFWLIB= $(ROOT)/usr/sfw/lib
+ROOTLIBEXEC= $(ROOT)/usr/sfw/libexec
+ROOTSFWMAN= $(ROOT)/usr/sfw/share/man
+ROOTSFWMANN= $(ROOT)/usr/sfw/share/mann
+ROOTSFWMAN1= $(ROOT)/usr/sfw/share/man/man1
+ROOTSFWMAN1M= $(ROOT)/usr/sfw/share/man/man1m
+ROOTSFWMAN3= $(ROOT)/usr/sfw/share/man/man3
+ROOTSFWMAN5= $(ROOT)/usr/sfw/share/man/man5
+ROOTSFWMAN7= $(ROOT)/usr/sfw/share/man/man7
+#
+# End /usr/sfw freeware rules
+#
+
+ISAEXEC= $(ROOT)/usr/lib/isaexec
+PLATEXEC= $(ROOT)/usr/lib/platexec
+
+NX_MAP_i386= $(SRC)/cmd/mapfile_noexdata
+NX_MAP_sparc=
+NX_MAP= $(NX_MAP_$(MACH))
+NES_MAPFILE= $(SRC)/cmd/mapfile_noexstk $(NX_MAP)
+
+LDLIBS = $(LDLIBS.cmd)
+
+LDFLAGS.cmd = \
+ $(STRIPFLAG) $(ENVLDFLAGS1) $(ENVLDFLAGS2) $(ENVLDFLAGS3) \
+ $(NES_MAPFILE:%=-M%) $(PGA_MAPFILE:%=-M%)
+
+LDFLAGS = $(LDFLAGS.cmd)
+
+LINTFLAGS= -axsm
+LINTFLAGS64= -axsm -Xarch=$(MACH64:sparcv9=v9)
+LINTOUT= lint.out
+
+KRB5PROG= $(PROG:%=$(KRB5BIN)/%)
+KRB5SBINPROG= $(PROG:%=$(KRB5SBIN)/%)
+KRB5LIBPROG= $(PROG:%=$(KRB5LIB)/%)
+
+ROOTPROG= $(PROG:%=$(ROOTBIN)/%)
+ROOTCMD= $(PROG:%=$(ROOTCMDDIR)/%)
+ROOTSHFILES= $(SHFILES:%=$(ROOTBIN)/%)
+ROOTLIBPROG= $(PROG:%=$(ROOTLIB)/%)
+ROOTLIBSHFILES= $(SHFILES:%=$(ROOTLIB)/%)
+ROOTSHLIBPROG= $(PROG:%=$(ROOTSHLIB)/%)
+ROOTSBINPROG= $(PROG:%=$(ROOTSBIN)/%)
+ROOTUSRSBINPROG=$(PROG:%=$(ROOTUSRSBIN)/%)
+ROOTETCPROG= $(PROG:%=$(ROOTETC)/%)
+ROOTCCSBINPROG= $(PROG:%=$(ROOTCCSBIN)/%)
+ROOTUSRKVMPROG= $(PROG:%=$(ROOTUSRKVM)/%)
+ROOTXPG4PROG= $(XPG4PROG:%=$(ROOTXPG4BIN)/%)
+ROOTXPG4PROG32= $(XPG4PROG:%=$(ROOTXPG4BIN32)/%)
+ROOTXPG4PROG64= $(XPG4PROG:%=$(ROOTXPG4BIN64)/%)
+ROOTXPG6PROG= $(XPG6PROG:%=$(ROOTXPG6BIN)/%)
+ROOTLOCALEPROG= $(PROG:%=$(ROOTLOCALEDEF)/%)
+ROOTPROG64= $(PROG:%=$(ROOTBIN64)/%)
+ROOTPROG32= $(PROG:%=$(ROOTBIN32)/%)
+ROOTCMD64= $(PROG:%=$(ROOTCMDDIR64)/%)
+ROOTUSRSBINPROG32= $(PROG:%=$(ROOTUSRSBIN32)/%)
+ROOTUSRSBINPROG64= $(PROG:%=$(ROOTUSRSBIN64)/%)
+ROOTMAN1FILES= $(MAN1FILES:%=$(ROOTMAN1)/%)
+$(ROOTMAN1FILES) := FILEMODE= 444
+$(ROOTMAN1FILES) := OWNER= root
+$(ROOTMAN1FILES) := GROUP= bin
+ROOTMAN1MFILES= $(MAN1MFILES:%=$(ROOTMAN1M)/%)
+$(ROOTMAN1MFILES) := FILEMODE= 444
+$(ROOTMAN1MFILES) := OWNER= root
+$(ROOTMAN1MFILES) := GROUP= bin
+ROOTMAN3FILES= $(MAN3FILES:%=$(ROOTMAN3)/%)
+$(ROOTMAN3FILES) := FILEMODE= 444
+$(ROOTMAN3FILES) := OWNER= root
+$(ROOTMAN3FILES) := GROUP= bin
+
+ROOTETCDEFAULT= $(ROOTETC)/default
+ROOTETCDEFAULTFILES= $(DEFAULTFILES:%=$(ROOTETCDEFAULT)/%)
+$(ROOTETCDEFAULTFILES) := OWNER = root
+$(ROOTETCDEFAULTFILES) := GROUP = sys
+$(ROOTETCDEFAULTFILES) := FILEMODE = 0444
+
+#
+# Directories for smf(5) service manifests and profiles.
+#
+ROOTVARSVC= $(ROOT)/var/svc
+
+ROOTVARSVCMANIFEST= $(ROOTVARSVC)/manifest
+ROOTVARSVCPROFILE= $(ROOTVARSVC)/profile
+
+ROOTSVCMILESTONE= $(ROOTVARSVCMANIFEST)/milestone
+ROOTSVCDEVICE= $(ROOTVARSVCMANIFEST)/device
+ROOTSVCSYSTEM= $(ROOTVARSVCMANIFEST)/system
+ROOTSVCSYSTEMDEVICE= $(ROOTSVCSYSTEM)/device
+ROOTSVCSYSTEMFILESYSTEM= $(ROOTSVCSYSTEM)/filesystem
+ROOTSVCSYSTEMSECURITY= $(ROOTSVCSYSTEM)/security
+ROOTSVCNETWORK= $(ROOTVARSVCMANIFEST)/network
+ROOTSVCNETWORKLDAP= $(ROOTSVCNETWORK)/ldap
+ROOTSVCNETWORKNFS= $(ROOTSVCNETWORK)/nfs
+ROOTSVCNETWORKNIS= $(ROOTSVCNETWORK)/nis
+ROOTSVCNETWORKRPC= $(ROOTSVCNETWORK)/rpc
+ROOTSVCNETWORKSECURITY= $(ROOTSVCNETWORK)/security
+ROOTSVCPLATFORM= $(ROOTVARSVCMANIFEST)/platform
+ROOTSVCPLATFORMI86PC= $(ROOTSVCPLATFORM)/i86pc
+ROOTSVCPLATFORMSUN4U= $(ROOTSVCPLATFORM)/sun4u
+ROOTSVCAPPLICATION= $(ROOTVARSVCMANIFEST)/application
+ROOTSVCAPPLICATIONMANAGEMENT= $(ROOTSVCAPPLICATION)/management
+ROOTSVCAPPLICATIONSECURITY= $(ROOTSVCAPPLICATION)/security
+ROOTSVCAPPLICATIONPRINT= $(ROOTSVCAPPLICATION)/print
+
+#
+# Commands Makefiles delivering a manifest are expected to define MANIFEST.
+#
+# Like ROOTCMDDIR, any lower-level Makefiles that put their manifests in a
+# subdirectory of the manifest directories listed above should reset
+# ROOTMANIFESTDIR and use it in their `install' target. By default we set this
+# to a bogus value so that it will not conflict with any of the other values
+# already defined in this Makefile.
+#
+# The manifest validation of the $SRC/cmd check target is also derived from a
+# valid MANIFEST setting.
+#
+ROOTMANIFESTDIR= $(ROOTVARSVCMANIFEST)/__nonexistent_directory__
+ROOTMANIFEST= $(MANIFEST:%=$(ROOTMANIFESTDIR)/%)
+CHKMANIFEST= $(MANIFEST:%.xml=%.xmlchk)
+
+#
+# For installing "starter scripts" of services
+#
+
+ROOTSVCBIN= $(SVCBIN:%=$(ROOTLIBSVCBIN)/%)
+ROOTSVCMETHOD= $(SVCMETHOD:%=$(ROOTLIBSVCMETHOD)/%)
+
+ROOTSVCBINDIR= $(ROOTLIBSVCBIN)/__nonexistent_directory__
+ROOTSVCBIN= $(SVCBIN:%=$(ROOTSVCBINDIR)/%)
+$(ROOTSVCBIN) := FILEMODE= 544
+
+#
+
+# For programs that are installed in the root filesystem,
+# build $(ROOTFS_PROG) rather than $(PROG)
+$(ROOTFS_PROG) := LDFLAGS += -Wl,-I/lib/ld.so.1
+
+$(KRB5BIN)/%: %
+ $(INS.file)
+
+$(KRB5SBIN)/%: %
+ $(INS.file)
+
+$(KRB5LIB)/%: %
+ $(INS.file)
+
+$(ROOTBIN)/%: %
+ $(INS.file)
+
+$(ROOTLIB)/%: %
+ $(INS.file)
+
+$(ROOTBIN64)/%: %
+ $(INS.file)
+
+$(ROOTLIB64)/%: %
+ $(INS.file)
+
+$(ROOTBIN32)/%: %
+ $(INS.file)
+
+$(ROOTSHLIB)/%: %
+ $(INS.file)
+
+$(ROOTSBIN)/%: %
+ $(INS.file)
+
+$(ROOTUSRSBIN)/%: %
+ $(INS.file)
+
+$(ROOTUSRSBIN32)/%: %
+ $(INS.file)
+
+$(ROOTUSRSBIN64)/%: %
+ $(INS.file)
+
+$(ROOTETC)/%: %
+ $(INS.file)
+
+$(ROOTCCSBIN)/%: %
+ $(INS.file)
+
+$(ROOTUSRKVM)/%: %
+ $(INS.file)
+
+$(ROOTXPG4BIN)/%: %.xpg4
+ $(INS.rename)
+
+$(ROOTXPG4BIN32)/%: %.xpg4
+ $(INS.rename)
+
+$(ROOTXPG4BIN64)/%: %.xpg4
+ $(INS.rename)
+
+$(ROOTXPG6BIN)/%: %.xpg6
+ $(INS.rename)
+
+$(ROOTLOCALEDEF)/%: %
+ $(INS.file)
+
+$(ROOTCHARMAP)/%: %
+ $(INS.file)
+
+$(ROOTI18NEXT)/%: %
+ $(INS.file)
+
+$(ROOTI18NEXT64)/%: %
+ $(INS.file)
+
+$(ROOTLIBSVCMETHOD)/%: %
+ $(INS.file)
+
+$(ROOTLIBSVCBIN)/%: %
+ $(INS.file)
+
+$(ROOTSVCMILESTONE)/%: %
+ $(INS.file)
+
+$(ROOTSVCDEVICE)/%: %
+ $(INS.file)
+
+$(ROOTSVCSYSTEM)/%: %
+ $(INS.file)
+
+$(ROOTSVCSYSTEMDEVICE)/%: %
+ $(INS.file)
+
+$(ROOTSVCSYSTEMFILESYSTEM)/%: %
+ $(INS.file)
+
+$(ROOTSVCSYSTEMSECURITY)/%: %
+ $(INS.file)
+
+$(ROOTSVCNETWORK)/%: %
+ $(INS.file)
+
+$(ROOTSVCNETWORKLDAP)/%: %
+ $(INS.file)
+
+$(ROOTSVCNETWORKNFS)/%: %
+ $(INS.file)
+
+$(ROOTSVCNETWORKNIS)/%: %
+ $(INS.file)
+
+$(ROOTSVCNETWORKRPC)/%: %
+ $(INS.file)
+
+$(ROOTSVCNETWORKSECURITY)/%: %
+ $(INS.file)
+
+$(ROOTSVCAPPLICATION)/%: %
+ $(INS.file)
+
+$(ROOTSVCAPPLICATIONMANAGEMENT)/%: %
+ $(INS.file)
+
+$(ROOTSVCAPPLICATIONSECURITY)/%: %
+ $(INS.file)
+
+$(ROOTSVCAPPLICATIONPRINT)/%: %
+ $(INS.file)
+
+$(ROOTSVCPLATFORM)/%: %
+ $(INS.file)
+
+$(ROOTSVCPLATFORMI86PC)/%: %
+ $(INS.file)
+
+$(ROOTSVCPLATFORMSUN4U)/%: %
+ $(INS.file)
+
+$(ROOTMAN1)/%: %.sunman
+ $(INS.rename)
+
+$(ROOTMAN1M)/%: %.sunman
+ $(INS.rename)
+
+$(ROOTMAN3)/%: %.sunman
+ $(INS.rename)
+
+# build rule for statically linked programs with single source file.
+%.static: %.c
+ $(LINK.c) -o $@ $< $(LDLIBS)
+ $(POST_PROCESS)
+
+%.xpg4: %.c
+ $(LINK.c) -o $@ $< $(LDLIBS)
+ $(POST_PROCESS)
+
+%.xpg6: %.c
+ $(LINK.c) -o $@ $< $(LDLIBS)
+ $(POST_PROCESS)
+
+# Define the majority text domain in this directory.
+TEXT_DOMAIN= SUNW_OST_OSCMD
+
+CLOBBERFILES += $(XPG4) $(XPG6) $(DCFILE)
+
+# This flag is being added only for SCO (x86) compatibility
+i386_SPFLAG= -D_iBCS2
+sparc_SPFLAG=
+
+iBCS2FLAG = $($(MACH)_SPFLAG)
+
+# This flag is for programs which should not build a 32-bit binary
+sparc_64ONLY= $(POUND_SIGN)
+64ONLY= $($(MACH)_64ONLY)
diff --git a/usr/src/cmd/Makefile.cmd.64 b/usr/src/cmd/Makefile.cmd.64
new file mode 100644
index 0000000..e0276a9
--- /dev/null
+++ b/usr/src/cmd/Makefile.cmd.64
@@ -0,0 +1,36 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# This makefile contains the compiler fiddling needed to build
+# 64-bit utilities.
+#
+
+include $(SRC)/Makefile.master.64
+
+V9CODESIZE = -xcode=abs44
+
+sparcv9_CFLAGS += $(V9CODESIZE)
diff --git a/usr/src/cmd/Makefile.cmd.bsm b/usr/src/cmd/Makefile.cmd.bsm
new file mode 100644
index 0000000..191dbdc
--- /dev/null
+++ b/usr/src/cmd/Makefile.cmd.bsm
@@ -0,0 +1,50 @@
+#
+# 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
+#
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Definitions common to BSM command source
+#
+# Before including this file you must set the PROG variable
+# and include Makefile.cmd
+#
+
+
+all:
+
+install: all $(ROOTUSRSBINPROG)
+
+# Rules for internationalization
+
+PO= $(TEXT_DOMAIN).po
+
+po: $(PO)
+
+$(PO): $(POS)
+ $(CAT) $(POS) > $@
+
+%.po: %.c
+ $(XGETTEXT) -c TRANSLATION_NOTE -d $(TEXT_DOMAIN) $<
+ $(MV) $(TEXT_DOMAIN).po $@
diff --git a/usr/src/cmd/Makefile.targ b/usr/src/cmd/Makefile.targ
new file mode 100644
index 0000000..6557291
--- /dev/null
+++ b/usr/src/cmd/Makefile.targ
@@ -0,0 +1,65 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# cmd/Makefile.targ
+# common target definitions for command builds
+#
+
+clobber: clean
+ -$(RM) $(PROG) $(CLOBBERFILES)
+
+lint_PROG: $$(PROG).c
+ $(LINT.c) $(PROG).c $(LDLIBS)
+
+lint_SRCS: $$(SRCS)
+ $(LINT.c) $(SRCS) $(LDLIBS)
+
+$(ROOTCMDDIR)/%: $(ROOTCMDDIR) %
+ $(INS.file)
+
+$(ROOTCMDDIR) $(ROOTCMDDIR64):
+ $(INS.dir)
+
+$(ROOTCMDDIR64)/%: $(ROOTCMDDIR64) %
+ $(INS.file)
+
+#
+# For message catalogue files
+#
+_msg: $(MSGDOMAIN) $(POFILE)
+ $(RM) $(MSGDOMAIN)/$(POFILE)
+ $(CP) $(POFILE) $(MSGDOMAIN)
+
+# the build of the $(DCFILE) should be defined locally
+# its .dc extension gets renamed to .po upon installation
+#
+_dc: $(DCMSGDOMAIN) $(DCFILE)
+ $(RM) $(DCMSGDOMAIN)/$(DCFILE)
+ $(CP) $(DCFILE) $(DCMSGDOMAIN)/$(DCFILE:.dc=.po)
+
+$(MSGDOMAIN) $(DCMSGDOMAIN):
+ $(INS.dir)
diff --git a/usr/src/cmd/OWconfig/Makefile b/usr/src/cmd/OWconfig/Makefile
new file mode 100644
index 0000000..1c948c2
--- /dev/null
+++ b/usr/src/cmd/OWconfig/Makefile
@@ -0,0 +1,76 @@
+#
+# 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
+#
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1999-2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# cmd/OWconfig/Makefile
+
+include ../Makefile.cmd
+
+FILES= OWconfig
+
+ROOTETC= $(ROOT)/etc
+OPENWIND= $(ROOTETC)/openwin
+OPENWINETCD= $(OPENWIND)/etc
+SERVERD= $(OPENWIND)/server
+SERVERETCD= $(SERVERD)/etc
+DEVDATAD= $(OPENWINETCD)/devdata
+SUNWACCELD= $(DEVDATAD)/SUNWaccel
+MONITORSD= $(SUNWACCELD)/monitors
+PDPD= $(MONITORSD)/pnp
+
+
+DIRS= \
+ $(ROOTETC) \
+ $(OPENWIND) \
+ $(OPENWINETCD) \
+ $(SERVERD) \
+ $(SERVERETCD) \
+ $(DEVDATAD) \
+ $(SUNWACCELD) \
+ $(MONITORSD) \
+ $(PDPD)
+
+FILEMODE=0644
+OWCONFIG=$(FILES:%=$(SERVERETCD)/%)
+
+$(SERVERETCD)/%: %
+ $(INS.file)
+
+
+.KEEP_STATE:
+
+all:
+
+install: all $(DIRS) $(OWCONFIG)
+
+$(DIRS):
+ -$(INS.dir)
+
+clean:
+
+lint:
+
+include ../Makefile.targ
diff --git a/usr/src/cmd/OWconfig/OWconfig b/usr/src/cmd/OWconfig/OWconfig
new file mode 100644
index 0000000..28104ca
--- /dev/null
+++ b/usr/src/cmd/OWconfig/OWconfig
@@ -0,0 +1 @@
+# Placeholder only - this file will not end up on the system.
diff --git a/usr/src/cmd/abi/Makefile b/usr/src/cmd/abi/Makefile
new file mode 100644
index 0000000..ddd7f9f
--- /dev/null
+++ b/usr/src/cmd/abi/Makefile
@@ -0,0 +1,45 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+SUBDIRS = spectrans apptracecmd appcert
+
+all := TARGET= all
+install := TARGET= install
+clean := TARGET= clean
+clobber := TARGET= clobber
+lint := TARGET= lint
+_msg := TARGET= _msg
+
+.KEEP_STATE:
+
+all install clean clobber lint _msg: $(SUBDIRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
diff --git a/usr/src/cmd/abi/Makefile.abi b/usr/src/cmd/abi/Makefile.abi
new file mode 100644
index 0000000..6b39a8f
--- /dev/null
+++ b/usr/src/cmd/abi/Makefile.abi
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+CPPFLAGS += -I../../common
+
+# We are compiling native, so disable the restricting
+# of library lookups to the local workspace.
+LDLIBS.cmd =
+LDLIBS.lib =
+
+# XXX -- temporary until the build machine's libc is updated
+ZDEFS = $(ZNODEFS)
diff --git a/usr/src/cmd/abi/appcert/Makefile b/usr/src/cmd/abi/appcert/Makefile
new file mode 100644
index 0000000..4d65df3
--- /dev/null
+++ b/usr/src/cmd/abi/appcert/Makefile
@@ -0,0 +1,53 @@
+#
+# 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) 1996-2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# cmd/abi/appcert/Makefile
+#
+
+.KEEP_STATE:
+BUILD = static_prof \
+ scripts \
+ etc
+
+APPCERT_MSGSUBDIRS = etc scripts
+
+all := TARGET= all
+install := TARGET= install
+clean := TARGET= clean
+clobber := TARGET= clobber
+lint := TARGET= lint
+_msg := TARGET= _msg
+
+all install clean clobber lint: $(BUILD)
+
+_msg: $(APPCERT_MSGSUBDIRS)
+
+$(BUILD): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
diff --git a/usr/src/cmd/abi/appcert/etc/Makefile b/usr/src/cmd/abi/appcert/etc/Makefile
new file mode 100644
index 0000000..4932431
--- /dev/null
+++ b/usr/src/cmd/abi/appcert/etc/Makefile
@@ -0,0 +1,80 @@
+#
+# 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) 1999-2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# cmd/abi/appcert/etc/Makefile
+#
+
+include $(SRC)/cmd/Makefile.cmd
+
+SUFFIXES += .in
+
+.KEEP_STATE:
+
+ROOTLIBAPPCERT= $(ROOT)/usr/lib/abi/appcert
+
+ETC_FILES = etc.alt etc.scoped etc.tweaks etc.warn
+MESSAGES = etc.warn.po
+ETC_FILES_SRC = $(ETC_FILES:%=%.in)
+
+DEST_FILES = $(ETC_FILES:%=$(ROOTLIBAPPCERT)/%)
+
+CLEANFILES= $(MESSAGES) $(ETC_FILES)
+
+install := FILEMODE= 0444
+install := DIRMODE= 0755
+install := OWNER= root
+install := GROUP= bin
+
+all: $(ETC_FILES)
+
+install: all .WAIT $(DEST_FILES)
+
+$(ROOTLIBAPPCERT)/%: %
+ $(INS.file)
+
+%: %.in
+ $(SED) -e 's,gettext("\([^"]*\)"),\1,' $< > $@
+
+_msg: $(MSGDOMAIN) $(MESSAGES)
+ $(CP) $(MESSAGES) $(MSGDOMAIN)
+
+$(MSGDOMAIN):
+ $(INS.dir)
+
+%.po: %.in
+ $(XGETTEXT) $(XGETFLAGS) $<
+ $(RM) $@
+ $(SED) "/^domain/d" messages.po > $@
+ $(RM) messages.po
+
+lint:
+
+clean:
+ -$(RM) $(CLEANFILES)
+
+clobber: clean
+
diff --git a/usr/src/cmd/abi/appcert/etc/etc.alt.in b/usr/src/cmd/abi/appcert/etc/etc.alt.in
new file mode 100644
index 0000000..1b092eb
--- /dev/null
+++ b/usr/src/cmd/abi/appcert/etc/etc.alt.in
@@ -0,0 +1,49 @@
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# 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
+#
+
+# syntax:
+#ALT_USAGE:<tag>:<1-line-desc>:<lib>:<sym>[|<sym>...]:<text>
+#
+# the label's and 1-line-desc's must be unique.
+# later <lib> basename may be added.
+# "\" may be used to continue a line. the newline is replaced by " ".
+# Another way to quote a block of text is to sandwich it between
+# single "-". The newline previous to the 1st "-" must be "\" quoted.
+# Special keywords in <expression>:
+# file =~ -> $file =~ where $file is `/bin/file /path/to/object`
+# dump =~ -> $dump =~ where $dump is `/usr/ccs/bin/dump /path/to/object`
+# needed =~ -> $needed =~ where $needed is a list of all needed libs.
+#
+#
+###############################################################################
+ALT_USAGE:libsocket_strong_symbols:libsocket.so weak/strong pairs:libsocket.so.1:_socket|_connect|_recv|_setsockopt|_getsockopt|_getsockname|_getpeername|_bind|_accept|_send|_socketpair|_shutdown|_sendto|_sendmsg|_recvmsg|_recvfrom|_listen|_setpeername|_socketpair_bsd|_socket_bsd:
+###############################################################################
+ALT_USAGE:inadvertant_static_linking:static linking inadevertantly brings in private symbols:*:__getcontext|__sigaction|__threaded|_bufsync|_cerror|_dgettext|_doprnt|_doscan|_ecvt|_fcvt|_findbuf|_findiop|_getsp|_memcmp|_memmove|_memset|_mutex_unlock|_psignal|_realbufend|_setbufend|_siguhandler|_smbuf|_thr_getspecific|_thr_keycreate|_thr_main|_thr_setspecific|_xflsbuf|gtty|stty:
+###############################################################################
+ALT_USAGE:getdomainname:possible getdomainname() replacements:libnsl.so.1:getdomainname:
+###############################################################################
+ALT_USAGE:__rpc_createerr:rpc_createerr can be a macro from <rpc/clnt.h>:libnsl.so.1:__rpc_createerr:
diff --git a/usr/src/cmd/abi/appcert/etc/etc.scoped.in b/usr/src/cmd/abi/appcert/etc/etc.scoped.in
new file mode 100644
index 0000000..277855a
--- /dev/null
+++ b/usr/src/cmd/abi/appcert/etc/etc.scoped.in
@@ -0,0 +1,1835 @@
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# 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
+#
+
+#
+# Special Cases Database. Locally scoped interfaces.
+#
+# Most of these are due to the local scoping the occurred in 5.6.
+#
+# SunOS 5.6
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|.div
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|.div_sw
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|.mul
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|.mul_sw
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|.rem
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|.rem_sw
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|.udiv
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|.udiv_sw
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|.umul
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|.umul_sw
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|.urem
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|.urem_sw
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|Errmsg_brdr
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|Errmsg_cmdz
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|Errmsg_cmfl
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|Errmsg_cmsg
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|Errmsg_cofl
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|Errmsg_cotf
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|Errmsg_csps
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|Errmsg_rbeo
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|Errmsg_rirt
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|Errmsg_rsnf
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|Errmsg_rupp
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|Errmsg_rupr
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|Errmsg_rvob
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|Errmsg_unft
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|Intmsg_relo
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|Lddmsg_fndl
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|Lddmsg_lequ
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|Lddmsg_lflp
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|Lddmsg_rsnf
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|___lwp_cond_wait
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|___lwp_mutex_lock
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|___lwp_mutex_unlock
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|__ctype
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|__lwp_cond_broadcast
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|__lwp_cond_signal
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|__lwp_continue
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|__lwp_create
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|__lwp_exit
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|__lwp_getprivate
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|__lwp_info
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|__lwp_kill
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|__lwp_mutex_lock
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|__lwp_mutex_trylock
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|__lwp_mutex_unlock
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|__lwp_self
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|__lwp_sema_init
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|__lwp_sema_post
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|__lwp_sema_wait
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|__lwp_setprivate
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|__lwp_sigredirect
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|__lwp_suspend
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|__lwp_wait
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|__xpg4
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_cerror
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_cerror64
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_close
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_ctype
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_exit
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_fcntl
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_fstat
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_ftruncate
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_getdents
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_getegid
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_geteuid
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_getgid
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_getpid
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_getuid
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_halt
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_kill
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_lock_clear
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_lock_try
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_lwp_cond_broadcast
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_lwp_cond_signal
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_lwp_continue
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_lwp_create
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_lwp_exit
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_lwp_getprivate
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_lwp_info
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_lwp_kill
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_lwp_mutex_lock
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_lwp_mutex_trylock
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_lwp_mutex_unlock
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_lwp_self
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_lwp_sema_init
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_lwp_sema_post
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_lwp_sema_wait
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_lwp_setprivate
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_lwp_sigredirect
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_lwp_suspend
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_lwp_wait
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_memcpy
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_memset
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_mmap
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_mprotect
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_munmap
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_profil
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_setup
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_sigprocmask
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_stat
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_strtok_r
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_sysconf
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_sysconfig
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_sysinfo
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_thr_errnop
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_thr_main
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_thr_min_stack
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|_truncate
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|addfree
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|analyze_so
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|aout_bndr
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|aout_fct
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|aout_lookup_sym
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|aout_plt_write
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|aout_reloc
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|aout_rtbndr
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|aout_set_prot
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|are_u_this
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|ask_db
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|bind_clear
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|bind_mode
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|bindlock
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|bound_add
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|bound_delete
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|boundlock
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|call_fini
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|call_init
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|caller
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|close
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|conv_reloc_type_str
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|copies
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|dbg_file
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|dbg_setup
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|dl_new_so
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|dl_old_so
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|dlp_delete
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|dlp_listadd
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|do_platform_token
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|doprf
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|dz_close
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|dz_init
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|dz_open
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|elf_bndr
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|elf_copy_reloc
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|elf_fct
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|elf_hash
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|elf_obj_file
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|elf_obj_fini
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|elf_plt_cg
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|elf_plt_init
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|elf_reloc
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|elf_set_prot
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|envdirs
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|envlist
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|envp
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|errno
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|fcntl
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|flags
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|fm_cleanup
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|fm_init
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|fmap
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|format
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|fstat
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|ftruncate
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|get_next_dir
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|getdents
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|getegid
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|geteuid
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|getgid
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|getpid
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|getuid
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|iflush_range
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|interp
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|is_so_loaded
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|kill
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|lasterr
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|lc_version
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|ldso_name
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|ldso_path
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|list_append
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|lm_append
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|lml_main
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|lml_rtld
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|lo_cache
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|load_so
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|malloclock
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|memset
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|mmap
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|mprotect
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|munmap
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|perm_free
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|perm_get
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|perm_set
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|perm_test
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|perm_unset
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|platform
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|plt_cg_interp
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|pr_name
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|preload
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|printf
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|printlock
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|profil
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|profile
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|profile_close
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|profile_dir
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|profile_name
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|profilelock
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|readenv
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|relocate_so
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|remove_so
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|rt_atfork
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|rt_mutex_lock
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|rt_mutex_unlock
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|rt_name
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|rtld_flags
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|rw_rdlock
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|rw_unlock
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|rw_wrlock
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|security
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|setup
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|sigprocmask
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|so_find
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|so_gen_path
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|stat
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|strchr
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|strncmp
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|strncpy
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|strpbrk
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|strspn
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|strtok_r
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|sysconf
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|sysinfo
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|syspagsz
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|thr_errnop
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|thr_main
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|thr_min_stack
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|thr_self
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|tracing
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|truncate
+SCOPED_SYMBOL|SunOS_5.6|ld.so.1|zero
+SCOPED_SYMBOL|SunOS_5.6|libXaw.so.5|clockClassRec
+SCOPED_SYMBOL|SunOS_5.6|libXaw.so.5|clockWidgetClass
+SCOPED_SYMBOL|SunOS_5.6|libXaw.so.5|logoClassRec
+SCOPED_SYMBOL|SunOS_5.6|libXaw.so.5|logoWidgetClass
+SCOPED_SYMBOL|SunOS_5.6|libXaw.so.5|mailboxClassRec
+SCOPED_SYMBOL|SunOS_5.6|libXaw.so.5|mailboxWidgetClass
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|_closelkfile
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|_enddgrptab
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|_freedevtabent
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|_freedgrptabent
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|_getdevrec
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|_getdevtabent
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|_getdgrprec
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|_getdgrptabent
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|_openlkfile
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|_putdevtabrec
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|_putdgrptabrec
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|_setdevtab
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|_setdgrptab
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|ckgrpfile
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|ckpwdfile
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|doremovecmd
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|oam_devtab
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|oam_dgroup
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|pkginfopen
+SCOPED_SYMBOL|SunOS_5.6|libadm.so.1|unreserv
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|__aio_cachefillcv
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|__aio_cachefilling
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|__aio_cachefillock
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|__aio_initlock
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|__aio_mutex
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|__aiosendsig
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|__aiostksz
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|__init_stacks
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|__pid
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|__sigio_masked
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|__sigio_maskedcnt
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|__sigio_pending
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|__sigio_pendinglock
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|__uaio_init
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|__uaio_ok
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_alloc_stack
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_cancel_off
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_cancel_on
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_cancel_work
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_cnt
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_create_worker
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_do_request
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_done_cv
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_done_head
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_done_tail
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_donecnt
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_forkinit
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_free_stack
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_free_stack_unlocked
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_hash_del
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_hash_insert
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_idle
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_idle_cv
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_lock
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_lwp_exec
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_outstand_cnt
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_req_add
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_req_alloc
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_req_done
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_req_free
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_req_get
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_unlock
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_work_done
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aio_worker_cnt
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aiopanic
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aioreqsize
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aiorw
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_aiowait_flag
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_alloc_stack
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_defaultstkcache
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_fill_aiocache
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_free_stack
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_halted
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_idle_workers
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_kaio_cleanup_thread
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_kaio_init
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_kaio_ok
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_kaiowp
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_lastworker
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_max_workers
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_maxworkload
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_min_workers
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_minworkload
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_nextworker
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_panic
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_sigio_enabled
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_worker_set
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|_workers
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|aio_pread
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|aio_pwrite
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|aiocancel_all
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|aiosigcancelhndlr
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|caller
+SCOPED_SYMBOL|SunOS_5.6|libaio.so.1|devzero
+SCOPED_SYMBOL|SunOS_5.6|libauth.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libauth.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libauth.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libauth.so.1|pam_debug
+SCOPED_SYMBOL|SunOS_5.6|libbsm.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libbsm.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libbsm.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libbsm.so.1|audit_halt_generic
+SCOPED_SYMBOL|SunOS_5.6|libbsm.so.1|audit_reboot_generic
+SCOPED_SYMBOL|SunOS_5.6|libbsm.so.1|auditstat
+SCOPED_SYMBOL|SunOS_5.6|libbsm.so.1|audituser
+SCOPED_SYMBOL|SunOS_5.6|libbsm.so.1|getkernstate
+SCOPED_SYMBOL|SunOS_5.6|libbsm.so.1|getuseraudit
+SCOPED_SYMBOL|SunOS_5.6|libbsm.so.1|setkernstate
+SCOPED_SYMBOL|SunOS_5.6|libbsm.so.1|setuseraudit
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|.div_sw
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|.mul_sw
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|.rem_sw
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|.udiv_sw
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|.umul_sw
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|.urem_sw
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|Msgdb
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|PASSWD
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_Msgdb
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_Q_set_exception
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__Xiswctype
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|___iswctype
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|___mul_65536_n
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|___wctype
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__arint_set_n
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__base_conversion_abort
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__base_conversion_set_exception
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__base_conversion_write_only_double
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__big_binary_to_big_decimal
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__big_binary_to_unpacked
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__big_decimal_to_big_binary
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__big_float_times_power
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__binary_to_decimal_fraction
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__binary_to_decimal_integer
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__carry_in_b10000
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__carry_propagate_ten
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__carry_propagate_two
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__class_double
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__class_extended
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__class_single
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__copy_big_float_digits
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__daytab
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__decimal_round
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__decimal_to_binary_fraction
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__decimal_to_binary_integer
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__decimal_to_unpacked
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__digits_to_double
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__doscan_u
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__double_to_digits
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__fgetwc_gen
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__first_link
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__four_digits_quick
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__four_digits_quick_table
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__fp_leftshift
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__fp_normalize
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__fp_rightshift
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__fp_set_exception
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__fpu_add3wc
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__fpu_cmpli
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__fpu_error_nan
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__fpu_neg2wc
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__fpu_normalize
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__fpu_rightshift
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__fpu_set_exception
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__fpu_sub3wc
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__fractionstring_to_big_decimal
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__free_big_float
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__get_ieee_flags
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__gtxt
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__infnanstring
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__inrange_double
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__inrange_quadex
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__inrange_single
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__integerstring_to_big_decimal
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__isenglish
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__isideogram
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__isnumber
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__isphonogram
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__isspecial
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__iswalnum
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__iswalpha
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__iswcntrl
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__iswdigit
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__iswgraph
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__iswlower
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__iswprint
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__iswpunct
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__iswspace
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__iswupper
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__iswxdigit
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__k_double_to_decimal
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__k_gconvert
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__k_quadruple_to_decimal
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__left_shift_base_ten
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__left_shift_base_two
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__lfmt_log
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__longquorem10000
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__lsearch_lock
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__lshift_b10000
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__mbftowc_gen
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__month_size
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__mul_10000short
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__mul_65536short
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__multiply_base_ten
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__multiply_base_ten_by_two
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__multiply_base_ten_vector
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__multiply_base_two
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__multiply_base_two_vector
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__pack_double
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__pack_extended
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__pack_quadruple
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__pack_single
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__pfmt_label
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__pfmt_nsev
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__pfmt_print
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__pfmt_sev_tab
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__prod_10000_b65536
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__prodc_b10000
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__quorem
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__quorem10000
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__right_shift_base_two
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__rtboot
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__sbrk_lock
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__set_ieee_flags
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__sigfillset
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__snprintf
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__tbl_10_big_digits
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__tbl_10_big_start
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__tbl_10_huge_digits
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__tbl_10_huge_start
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__tbl_10_small_digits
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__tbl_10_small_start
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__tbl_2_big_digits
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__tbl_2_big_start
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__tbl_2_huge_digits
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__tbl_2_huge_start
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__tbl_2_small_digits
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__tbl_2_small_start
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__tbl_baselg
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__tbl_ntens
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__tbl_tens
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__towlower
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__towupper
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__treelock
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__trwctype
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__umac
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__unpack_double
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__unpack_double_two
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__unpack_extended
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__unpack_extended_two
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__unpack_quadruple_two
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__unpack_single
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__unpack_single_two
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__unpackdouble
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__unpackllong
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__unpacksingle
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__utx_lock
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__vsnprintf
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__wcschr
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__wcslen
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__wcswidth_gen
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__wcwidth_gen
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__wschr
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__wslen
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|__year_lengths
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_alt_digits
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_brk_unlocked
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_check_threaded
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_clearerr_unlocked
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_coll_get_order
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_collate_category_changed
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_cur_locale
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_dirent_lock
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_dl_zero
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_dostrfmon_unlocked
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_eras
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_eucwidth
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_feof_unlocked
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_ferror_unlocked
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_fexecve
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_fflush_u
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_fileno_unlocked
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_flockget
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_flockrel
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_fp_add
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_fp_compare
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_fp_current_direction
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_fp_current_exceptions
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_fp_current_precision
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_fp_div
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_fp_mul
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_fp_pack
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_fp_sqrt
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_fp_sub
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_fp_unpack
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_free_unlocked
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_fullocale
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_fwrite_unlocked
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_get_coll_elm
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_get_encoded_value
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_get_r_weight_mbs
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_get_r_weight_wcs
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_gethz
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_id2str
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_libc_alarm
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_libc_calloc
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_libc_fork
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_libc_fork1
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_libc_free
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_libc_malloc
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_libc_realloc
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_libc_set_threaded
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_libc_setitimer
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_libc_sigaction
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_libc_siglongjmp
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_libc_sigwait
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_libc_sleep
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_libc_unset_threaded
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_loc_filename
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_localeconv_nolock
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_locktab
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_lsign
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_ltostr
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_m_cclass
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_m_collequiv
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_m_collorder
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_m_collrange
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_m_colltostr
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_m_getmccoll
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_m_getwmccoll
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_m_ismccollel
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_m_m_collequiv
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_m_m_collorder
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_m_m_collrange
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_m_m_colltostr
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_m_m_getmccoll
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_m_m_maxcoll
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_m_m_strtocoll
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_m_mbstowcsdup
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_m_strtocoll
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_m_wcstombsdup
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_mblen_gen
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_mbrtowc
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_mbstowcs
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_mbstowcs_gen
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_mbtowc_gen
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_mcount_newent
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_modut
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_nativeloc
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_nss_XbyY_fgets
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_nss_initf_group
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_nss_initf_passwd
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_nss_initf_shadow
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_nss_src_state_destr
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_nss_status_vec
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_nsw_getoneconfig
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_num_alt_digits
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_num_eras
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_pcmask
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_reallock
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_reg_m_mbstowcsdup
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_rewind_unlocked
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_rmutex_trylock
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_rw_pfmt_label
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_rw_pfmt_sev_tab
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_set_tab
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_split_double_19
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_split_double_3
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_split_double_35
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_split_double_51
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_split_double_52
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_split_double_m1
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_split_shorten
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_split_single_22
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_split_single_23
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_split_single_6
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_split_single_m1
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_str2id
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_strcoll_dyn
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_strcoll_xpg4
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_strxfrm_dyn
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_strxfrm_xpg4
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_sys_polllist
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_sys_siginfolist
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_thr_get_direction
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_thr_get_exceptions
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_thr_get_inf_written
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_thr_get_nan_written
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_thr_get_precision
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_time_lock
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_tsdalloc
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_unpacked_to_decimal_two
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_updutfile
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_updutmp
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_updutmpx
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_updutxfile
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_wchar_opt
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_wcstombs
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_wcstombs_gen
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_wctoce
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|_wctomb_gen
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|charmap
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|classtest
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|clearerr_unlocked
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|close_fd
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|dbm_firsthash
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|dbm_flush
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|dbm_flushdir
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|dbm_flushpag
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|dbm_forder
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|dummy_setlocale
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|extract_era_info
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|feof_unlocked
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|ferror_unlocked
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|fileno_unlocked
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|fnwnmatch
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|fnwwmatch
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|fp_mblen
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|fp_mbstowcs
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|fp_mbtowc
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|fp_wcstombs
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|fp_wctomb
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|gethz
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|handle_return
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|id2str
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|ieee_handlers
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|invoke_utmp_update
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|isdevice
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|libc_yp_first
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|libc_yp_get_default_domain
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|libc_yp_match
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|libc_yp_next
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|lsign
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|modut
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|okshells
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|regsbdosub
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|regsbdosuba
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|regwcomp
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|regwdosuba
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|regwexec
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|sendpid
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|setup_collate
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|str2group
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|str2id
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|str2passwd
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|strcoll_C
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|strxfrm_C
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|syssun
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|updutfile
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|updutmp
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|updutmpx
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|updutxfile
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|utmpfile
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|utmpxfile
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|wisprint
+SCOPED_SYMBOL|SunOS_5.6|libc.so.1|xpg4_dfl_fmt
+SCOPED_SYMBOL|SunOS_5.6|libdl.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libdl.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libdoor.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libdoor.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libdoor.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf32_ehdr_init
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf32_entsz
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf32_msize
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf32_mtype
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_app_String
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_arinit
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_armem
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_byte
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_cook
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_cookscn
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_demangle_doarg
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_demangle_doargs
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_dnode
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_encode
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_findop
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_free_String
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_inmap
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_jbuf
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_mk_String
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_napp_String
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_nplist
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_nprep_String
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_outmap
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_prep_String
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_read
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_set_String
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_snode
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_snode_init
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_trunc_String
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_unmap
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_vm
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_elf_work
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libelf.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libintl.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libintl.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libintl.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libintl.so.1|category_to_name
+SCOPED_SYMBOL|SunOS_5.6|libintl.so.1|defaultbind
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|FreeParameterSet
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|ParmCompare
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|_C0095B2A
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|_C0095B2B
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|_C0095B2C
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|_C0095C2A
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|_C0095C2B
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|ad_print
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|com_err
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|com_err_hook
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|com_perror
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|create_ciph
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|decomp_ticket
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|des_cbc_cksum
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|des_cblock_print_file
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|des_check_key_parity
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|des_debug
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|des_fixup_key_parity
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|des_generate_random_block
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|des_init_random_number_generator
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|des_is_weak_key
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|des_key_sched
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|des_new_random_key
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|des_quad_cksum
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|des_random_key
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|des_read_password
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|des_read_pw_string
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|des_set_random_generator_seed
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|des_set_sequence_number
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|des_string_to_key
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|error_message
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|extract_ticket
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|fGetChar
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|fGetKeywordValue
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|fGetLiteral
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|fGetParameterSet
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|fGetToken
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|fUngetChar
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|fgetst
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|get_ad_tkt
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|get_pw_tkt
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|get_request
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|getst
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|in_tkt
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|init_error_table
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|init_krb_err_tbl
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|kerb_dogrouplist
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|krb_ap_req_debug
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|krb_create_ticket
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|krb_debug
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|krb_err_base
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|krb_get_in_tkt
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|krb_get_tf_fullname
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|krb_set_lifetime
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|krb_udp_port
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|krb_use_nis
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|kset_logfile
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|kuserok
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|month_sname
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|new_log
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|pkt_clen
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|private_msg_ver
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|read_service_key
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|rep_err_code
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|reset_com_err_hook
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|save_credentials
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|send_to_kdc
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|set_com_err_hook
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|set_logfile
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|strsave
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|strutol
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|svcauthkerb_stats
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|swap_bytes
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|tf_save_cred
+SCOPED_SYMBOL|SunOS_5.6|libkrb.so.1|tt_local
+SCOPED_SYMBOL|SunOS_5.6|libkstat.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libkstat.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libkstat.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libkvm.so.1|__kvm_getkvar
+SCOPED_SYMBOL|SunOS_5.6|libkvm.so.1|__kvm_kvtop
+SCOPED_SYMBOL|SunOS_5.6|libkvm.so.1|__kvm_openerror
+SCOPED_SYMBOL|SunOS_5.6|libkvm.so.1|_anonoffset
+SCOPED_SYMBOL|SunOS_5.6|libkvm.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libkvm.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libkvm.so.1|_kvm_physaddr
+SCOPED_SYMBOL|SunOS_5.6|libkvm.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libkvm.so.1|_swapread
+SCOPED_SYMBOL|SunOS_5.6|libkvm.so.1|_uncondense
+SCOPED_SYMBOL|SunOS_5.6|libkvm.so.1|kvm_as_rdwr
+SCOPED_SYMBOL|SunOS_5.6|libkvm.so.1|kvm_as_write
+SCOPED_SYMBOL|SunOS_5.6|libld.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libld.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libld.so.1|conv_reloc_type_str
+SCOPED_SYMBOL|SunOS_5.6|libld.so.1|format
+SCOPED_SYMBOL|SunOS_5.6|libld.so.1|list_append
+SCOPED_SYMBOL|SunOS_5.6|liblddbg.so.2|_fini
+SCOPED_SYMBOL|SunOS_5.6|liblddbg.so.2|_init
+SCOPED_SYMBOL|SunOS_5.6|liblddbg.so.2|conv_reloc_type_str
+SCOPED_SYMBOL|SunOS_5.6|liblddbg.so.2|format
+SCOPED_SYMBOL|SunOS_5.6|liblm.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|liblm.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|liblm.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libmapmalloc.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libmapmalloc.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libmapmalloc.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libmapmalloc.so.1|malloc_debug
+SCOPED_SYMBOL|SunOS_5.6|libmapmalloc.so.1|malloc_verify
+SCOPED_SYMBOL|SunOS_5.6|libmapmalloc.so.1|mallocmap
+SCOPED_SYMBOL|SunOS_5.6|libmapmalloc.so.1|memstart
+SCOPED_SYMBOL|SunOS_5.6|libmp.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libmp.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libmp.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libmp.so.1|_mp_fatal
+SCOPED_SYMBOL|SunOS_5.6|libmp.so.1|_mp_mcan
+SCOPED_SYMBOL|SunOS_5.6|libmp.so.1|fmin
+SCOPED_SYMBOL|SunOS_5.6|libmp.so.1|fmout
+SCOPED_SYMBOL|SunOS_5.6|libmp.so.1|invert
+SCOPED_SYMBOL|SunOS_5.6|libmp.so.1|m_add
+SCOPED_SYMBOL|SunOS_5.6|libmp.so.1|m_div
+SCOPED_SYMBOL|SunOS_5.6|libmp.so.1|m_dsb
+SCOPED_SYMBOL|SunOS_5.6|libmp.so.1|m_mult
+SCOPED_SYMBOL|SunOS_5.6|libmp.so.1|m_sub
+SCOPED_SYMBOL|SunOS_5.6|libmp.so.1|m_trq
+SCOPED_SYMBOL|SunOS_5.6|libmp.so.1|omin
+SCOPED_SYMBOL|SunOS_5.6|libmp.so.1|omout
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|FreeDictionary
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|InUseDictionary
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|_fini
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|_init
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|copy_entry
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|curdict
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|db_apply_log_entry
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|db_log_entries_since
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|db_print_all_indices
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|db_print_index
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|db_print_table_names
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|db_stats
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|db_update_version
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|db_version
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|dbenv
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|make_zero
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|new_entry
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|tempdict
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_action
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_attrname
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_data_desc
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_dict_desc
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_dict_desc_p
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_dict_version
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_dictlog_entry
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_dictlog_entry_p
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_dictlog_list
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_free_entry
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_free_entry_p
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_free_list
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_free_list_p
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_index
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_index_entry
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_index_entry_p
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_index_p
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_key_desc
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_log_entry
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_log_entry_p
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_log_list
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_mindex
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_mindex_p
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_next_desc
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_posn_info
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_qcomp
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_query
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_request
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_result
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_scheme
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_scheme_p
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_status
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_stringname
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_table
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_table_desc
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_table_desc_p
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_db_table_p
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_entry_object
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_entry_object_p
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_entryp
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_item
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_nullptr
+SCOPED_SYMBOL|SunOS_5.6|libnisdb.so.2|xdr_vers
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__classic_netdir_getbyaddr
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__classic_netdir_getbyname
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__clear_directory_local
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__inet_address_is_local
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__inet_netdir_options
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__inet_taddr2uaddr
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__inet_uaddr2taddr
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__is_xdrrec_first
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__nis_CacheRefreshEntry
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__nis_cast
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__nis_flush_one_group
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__nis_librand
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__nis_max_hard_lookup_time
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__nis_nextsep_of
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__nis_no_preference
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__nis_preferred_lock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__nis_set_preference
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__nis_splice_name_r
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__nis_swap_endpoints
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__nisipbufsize
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__rpc_get_time_offset
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__rpc_minfd
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__rpc_openchild
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__rpc_raise_fd
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__rpcb_findaddr
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__rpcb_findaddr_timed
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__svc_vc_setflag
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__svc_versquiet_get
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__svc_versquiet_off
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__svc_versquiet_on
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__svcauth_null
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__svcauth_short
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__svcauth_sys
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__svcauth_unix
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__td_setnodelay
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__xdrrec_resetfirst
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__xdrrec_setfirst
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__yp_dobind_rsvdport
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|__ypipbufsize
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_door_gethostbyaddr_r
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_door_gethostbyname_r
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_libnsl_lock_init
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_nss_initf_hosts
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_nss_initf_rpc
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_svc_destroy_private
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_svc_dg_destroy_private
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_svc_prog_dispatch
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_svc_vc_destroy_private
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_switch_getservbyname_r
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_switch_getservbyport_r
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_t_aligned_copy
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_t_blockallsignals
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_t_checkfd
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_t_create
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_t_do_ioctl
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_t_is_event
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_t_is_ok
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_t_look_locked
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_t_restoresigmask
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_t_tsdalloc
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_ti_userlock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_ypserv_timeout
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|_ypsleeptime
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|add_to_xlate_list
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|additem
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|authdes_cachesz
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|authdes_pk_seccreate
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|authnone_lock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|authsvc_lock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|chkblk
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|clnt_fd_lock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|clntraw_lock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|cmpdatum
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|dbm_access
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|dbmflush
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|delitem
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|destroy_err_buf
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|dname_lock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|do_cpy
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|dupreq_lock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|forder
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|free_dom_binding
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|g_cache_lock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|getbit
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|hent2ndaddr
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|hitab
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|hltab
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|hsents2ndhostservs
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|keyserv_lock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|libnsl_trace_lock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|lock_value
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|loopnconf_lock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|lowvers
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|mem_err_msg_arr
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|mem_err_msg_ref
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|ndaddr2hent
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|ndaddr2srent
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|ndhostserv2hent
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|ndhostserv2srent
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|netpp_mutex
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_add_clnt
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_cache_add_entry_1
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_cache_read_coldstart_1
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_cache_refresh_entry_1
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_cache_remove_entry_1
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_callback_clnt
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_checkpoint_clnt
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_clone_object_r
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_cptime_clnt
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_data_r
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_dump_clnt
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_dump_r
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_dumplog_clnt
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_dumplog_r
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_finddirectory_clnt
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_flush_namelist
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_flush_table
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_ibadd_clnt
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_ibfirst_clnt
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_iblist_clnt
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_ibmodify_clnt
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_ibnext_clnt
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_ibremove_clnt
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_lookup_clnt
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_mkdir_clnt
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_modify_clnt
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_name_of_r
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_old_data_r
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_ping_clnt
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_print_server
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_remove_clnt
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_rmdir_clnt
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_scan_table
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_servstate_clnt
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_sort_directory_servers
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_status_clnt
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|nis_updkeys_clnt
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|ops_lock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|order_haddrlist
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|partab
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|portnum_lock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|proglst_lock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|rpc_nullproc
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|rpcbaddr_cache_lock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|rpcsoc_lock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|serialize_pkey
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|setbit
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|srv_cache_lock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|str2hostent
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|str2rpcent
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_args_done
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_copy
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_dg_create_private
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_dg_xprtcopy
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_dg_xprtfree
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_exit_mutex
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_fd_create_private
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_fd_lock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_fd_xprtcopy
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_fd_xprtfree
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_lock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_max_fd
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_mt_mode
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_mutex
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_nfds
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_nfds_set
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_pipe
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_polling
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_thr_fdwait
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_thr_mutex
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_vc_create_private
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_vc_xprtcopy
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_vc_xprtfree
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_versquiet
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_xdrs
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_xports
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svc_xprt_destroy
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svcauthdes_stats
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|svcraw_lock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|thr_get_storage
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|thr_sigblock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|tsd_lock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|writeColdStartFile_unsafe
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|xdr_entry_col
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|xdr_group_obj
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|xdr_link_obj
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|xdr_log_entry_t
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|xdr_netconfig
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|xdr_nis_tag
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|xdr_nstype
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|xdr_oar_mask
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|xdr_passwd
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|xdr_table_col
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|xdr_ypbind_binding
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|xdr_ypreq_newname_string
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|xdr_zotypes
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|xprtlist_lock
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|ypbindproc_null_3
+SCOPED_SYMBOL|SunOS_5.6|libnsl.so.1|ypbindproc_setdom_3
+SCOPED_SYMBOL|SunOS_5.6|libposix4.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libposix4.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libposix4.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libpthread.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libpthread.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libpthread.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libpthread.so.1|_sema_wait_cancel
+SCOPED_SYMBOL|SunOS_5.6|libpthread.so.1|_thr_errnop
+SCOPED_SYMBOL|SunOS_5.6|librac.so.1|__rpcb_findaddr
+SCOPED_SYMBOL|SunOS_5.6|librac.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|librac.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|librac.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|librac.so.1|free_pkt
+SCOPED_SYMBOL|SunOS_5.6|librac.so.1|free_pollinfo
+SCOPED_SYMBOL|SunOS_5.6|librac.so.1|pkt_vc_poll
+SCOPED_SYMBOL|SunOS_5.6|librac.so.1|pkt_vc_read
+SCOPED_SYMBOL|SunOS_5.6|librac.so.1|ri_to_xid
+SCOPED_SYMBOL|SunOS_5.6|librac.so.1|xdrrec_resetinput
+SCOPED_SYMBOL|SunOS_5.6|libresolv.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libresolv.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libresolv.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libresolv.so.1|putshort
+SCOPED_SYMBOL|SunOS_5.6|libresolv.so.1|res_sethostfile
+SCOPED_SYMBOL|SunOS_5.6|librpcsoc.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|librpcsoc.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|librpcsoc.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|librpcsvc.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|librpcsvc.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|librpcsvc.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|librpcsvc.so.1|rusers3
+SCOPED_SYMBOL|SunOS_5.6|librpcsvc.so.1|xdr_ru_utmp
+SCOPED_SYMBOL|SunOS_5.6|librpcsvc.so.1|xdr_utmpidle
+SCOPED_SYMBOL|SunOS_5.6|librpcsvc.so.1|xdr_utmpidleptr
+SCOPED_SYMBOL|SunOS_5.6|libsec.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libsec.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libsec.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|__accept
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|__bind
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|__getpeername
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|__getsockname
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|__setsockopt
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_connect2
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_s_aligned_copy
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_s_blockallsignals
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_s_cbuf_alloc
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_s_checkfd
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_s_close
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_s_cpaddr
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_s_do_ioctl
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_s_is_ok
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_s_max
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_s_min
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_s_rcv_conn_con
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_s_restoresigmask
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_s_snd_conn_req
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_s_sockdebug
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_s_socreate
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_s_soreceivexx
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_s_sosendxx
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_s_synch
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_s_uxpathlen
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_switch_getservbyname_r
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|_switch_getservbyport_r
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|callselect
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|find_silink
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|s_getfflags
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|s_invalfflags
+SCOPED_SYMBOL|SunOS_5.6|libsocket.so.1|setsockname
+SCOPED_SYMBOL|SunOS_5.6|libsys.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libsys.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|TR_rf
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_SHAREDFRAME
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__advance_pc_if_munlock_segv
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__alarm
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__alarm_sigaction
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__bounceself
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__dynamic_tid
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__fork
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__fork1
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__ksigsok
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__libthread_segvhdlr
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__lwp_alarm
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__lwpdirsigs
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__null_sigaction
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__pseudosynch
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__segv_sigaction
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__sendsig
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__setcontext
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__setitimer
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__sig_resethand
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__sighandler_lock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__sighandler_unlock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__sigprocmask
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__sigsuspend_trap
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__sigtimedwait_trap
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__thr_continue
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__thr_kill
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__thr_sigredirect
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__thr_sigsetmask
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__unsafe_bsigs
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|__wrd
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_age
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_aging
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_allmasked
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_alloc_attr
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_alloc_stack
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_alloc_thread
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_alloc_tmpstack
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_allthreads
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_allunmasked
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_blocking
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_blocksent
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_bpending
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_bpendinglock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_bsigs
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_callin
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_calloutcnt
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_calloutlock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_calloutp
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_cantmask
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_cantreset
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_choose_thread
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_co_set
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_co_tid
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_cond_eot
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_curthread
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_d2bzombies
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_defaultstkcache
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_deliversigs
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_destroy_tsd
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_dispdeq
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_dispinit
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_dispq
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_dopreempt
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_dqactmap
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_dynamic_create
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_dynamiclwps
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_ex_clnup_handler
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_ex_unwind_local
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_first_thr_create
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_flush_and_tell
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_flush_user_windows
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_free_attr
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_free_stack
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_free_tmpstack
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_fsig
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_getcaller
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_getpc
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_getpsr
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_halted
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_hibit
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_idle_thread_create
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_idtot
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_ignoredefault
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_init_cpu
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_initsigs
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_lasttid
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_lcantmask
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_libpthread_loaded
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_lmutex_lock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_lmutex_trylock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_lmutex_unlock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_lpagesize
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_lpostfork_child_handler
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_lpostfork_parent_handler
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_lprefork_handler
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_lpthread_atfork
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_lrw_rdlock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_lrw_unlock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_lrw_wrlock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_lwp_exec
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_lwp_exitp
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_lwp_mutex_unlockp
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_lwp_terminate
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_maxpriq
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_minlwps
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_minpri
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_mutex_op_lock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_mutex_op_unlock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_mutex_sema_unlock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_mutex_unlock_asm
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_nagewakecnt
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_naging
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_ndie
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_new_lwp
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_nidle
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_nidlecnt
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_nlwps
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_nrunnable
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_nthreads
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_null_sigset
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_onproc_deq
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_onproc_enq
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_onprocq
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_onprocq_size
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_panic
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_pmask
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_pmasklock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_postfork_child_handler
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_postfork_parent_handler
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_preempt
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_preempt_off
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_preempt_on
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_prefork_handler
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_qswtch
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_reap_lock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_reap_unlock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_reap_wait
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_reap_wait_cancel
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_reapcnt
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_reaper_create
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_reaplock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_reaplockp
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_reapq_add
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_resetlib
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_restorefsr
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_rmcallout
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_rwlsub_lock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_rwlsub_unlock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_save_thread
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_savefsr
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_sched_lock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_sched_lock_nosig
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_sched_owner
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_sched_ownerpc
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_sched_unlock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_sched_unlock_nosig
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_schedlock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_setcallout
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_setpsr
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_setrq
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_setrun
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_setsighandler
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_sigcancel
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_sighandlerlock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_siglwp
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_siglwp_handler
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_sigmaskset
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_sigredirect
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_sigunblock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_sigwait_cv
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_sigwaiting_enabled
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_sigwaitingset
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_slpq
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_stack_switch
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_stkcachelock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_suspended
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_switch_stack
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_swtch
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_t0
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_t0init
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_t_block
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_t_cancel
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_t_release
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_t_release_all
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_t_setitimer
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_tcancel_all
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_thr_exit_common
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_thread
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_thread_call
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_thread_destroy
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_thread_free
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_thread_probe_getfunc
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_thread_ret
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_thread_start
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_threadjmp
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_threadoffset
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_thrp_create
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_thrp_exit
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_thrp_join
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_thrp_kill_unlocked
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_tidlock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_tidtotls
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_timerset
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_tlsbase
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_tlstotid
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_totalmasked
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_totalthreads
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_tpmask
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_tsiguhandler
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_tsslock
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_u2bzombies
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_unpark
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_unsleep
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_untilreaped
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_userthreads
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_zombiecnt
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_zombied
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|_zombies
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|caller
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|devzero
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|hrestime
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|setcontext_masksigs
+SCOPED_SYMBOL|SunOS_5.6|libthread.so.1|tsd_common
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.0|_fini
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.0|_init
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.0|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.0|thread_db_stksegment
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.1|__gd_lock
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.1|__map_fp_pr2reg
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.1|__map_fp_reg2pr
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.1|__td_debug
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.1|__td_dread_process
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.1|__td_dwrite_process
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.1|__td_logging
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.1|__td_pub_debug
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.1|__td_read_thr_struct
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.1|__td_read_thread_hash_tbl
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.1|__td_sigmask_are_equal
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.1|__td_ta_map_addr2thr
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.1|__td_thr_map_state
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.1|__td_write_thr_struct
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.1|_tpmask
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.1|diag_print
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.1|td_global_events
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.1|td_sync_type_names
+SCOPED_SYMBOL|SunOS_5.6|libthread_db.so.1|td_ta_map_addr2thr
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_check_array
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_check_datum
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_check_record
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_check_slots
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_check_type
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_error
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_fini_tags
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_align
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_base_tag
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_chars
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_derived_base
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_element_count
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_element_named
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_elements
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_header_size
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_info
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_kind
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_name
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_properties
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_property
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_props
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_ref16
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_ref32
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_ref_size
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_root_tag
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_self_size
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_slot_named
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_slot_typed
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_slot_types
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_storage_size
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_tag
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_get_tag_arg
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_init_tags
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_record_info
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_swap16
+SCOPED_SYMBOL|SunOS_5.6|libtnf.so.1|_tnf_swap32
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|_tnf_buf_headers_p
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|_tnf_fork
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|_tnf_fork1
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|_tnf_fork_thread_setup
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|_tnf_resume_ret
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|_tnf_sched_init
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|_tnf_trace_initialize
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|_tnf_vfork
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_abstract_tag_1
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_align_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_array_properties
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_array_slots
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_array_tag_1
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_array_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_array_type_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_block_header_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_derived_base_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_derived_properties
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_derived_tag_1
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_derived_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_derived_type_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_element_type_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_file_header_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_header_size_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_inline_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_name_array_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_no_properties
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_probe_tag
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_probe_type_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_properties_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_scalar_properties
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_scalar_tag_1
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_scalar_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_scalar_type_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_sched_rec_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_schedule_write
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_self_size_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_slot_names_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_slot_types_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_string_array_1
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_struct_properties
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_struct_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_struct_type_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_tag_arg_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_tag_array_1
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_tag_element_1
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_tag_properties_1
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_tagged_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_trace_initial_tpd
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_type_array_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_type_properties
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_type_size_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnf_type_tag_data
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnfw_b_alloc
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnfw_b_atomic_swap
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnfw_b_clear_lock
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnfw_b_fw_alloc
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnfw_b_get_lock
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnfw_b_init_buffer
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnfw_b_xabort
+SCOPED_SYMBOL|SunOS_5.6|libtnfprobe.so.1|tnfw_b_xcommit
+SCOPED_SYMBOL|SunOS_5.6|libucb.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libucb.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libucb.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libucb.so.1|cnvtvfs
+SCOPED_SYMBOL|SunOS_5.6|libucb.so.1|dc
+SCOPED_SYMBOL|SunOS_5.6|libucb.so.1|ucbsignal
+SCOPED_SYMBOL|SunOS_5.6|libucb.so.1|wstat
+SCOPED_SYMBOL|SunOS_5.6|libvolmgt.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libvolmgt.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libvolmgt.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libvolmgt.so.1|_regcmp
+SCOPED_SYMBOL|SunOS_5.6|libvolmgt.so.1|_regex
+SCOPED_SYMBOL|SunOS_5.6|libvolmgt.so.1|getrawpart0
+SCOPED_SYMBOL|SunOS_5.6|libvolmgt.so.1|volmgt_completename
+SCOPED_SYMBOL|SunOS_5.6|libvolmgt.so.1|volmgt_getfullblkname
+SCOPED_SYMBOL|SunOS_5.6|libvolmgt.so.1|volmgt_getfullrawname
+SCOPED_SYMBOL|SunOS_5.6|libw.so.1|_fgetwc_unlocked
+SCOPED_SYMBOL|SunOS_5.6|libw.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libw.so.1|_init
+SCOPED_SYMBOL|SunOS_5.6|libw.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.6|libw.so.1|_wcscoll_dyn
+SCOPED_SYMBOL|SunOS_5.6|libw.so.1|_wcscoll_xpg4
+SCOPED_SYMBOL|SunOS_5.6|libw.so.1|_wcsxfrm_dyn
+SCOPED_SYMBOL|SunOS_5.6|libw.so.1|_wcsxfrm_xpg4
+SCOPED_SYMBOL|SunOS_5.6|libw.so.1|_wssize
+SCOPED_SYMBOL|SunOS_5.6|libw.so.1|_xpg4_wcscoll
+SCOPED_SYMBOL|SunOS_5.6|libw.so.1|_xpg4_wcsxfrm
+SCOPED_SYMBOL|SunOS_5.6|libw.so.1|mbftowc
+SCOPED_SYMBOL|SunOS_5.6|libxfn.so.1|_fini
+SCOPED_SYMBOL|SunOS_5.6|libxfn.so.1|_init
+#
+# SunOS 5.7
+SCOPED_SYMBOL|SunOS_5.7|libresolv.so.2|__p_rr
+#
+# appcert 2.5
+SCOPED_SYMBOL|SunOS_5.10|libadm.so.1|sysmem
+SCOPED_SYMBOL|SunOS_5.10|libadm.so.1|asysmem
+SCOPED_SYMBOL|SunOS_5.10|libaio.so.1|_aiosigaction
+SCOPED_SYMBOL|SunOS_5.10|libaio.so.1|_pagesize
+SCOPED_SYMBOL|SunOS_5.10|libaio.so.1|__aio_suspend64
+SCOPED_SYMBOL|SunOS_5.10|libaio.so.1|__libaio_fdsync
+SCOPED_SYMBOL|SunOS_5.10|libaio.so.1|__libaio_pread
+SCOPED_SYMBOL|SunOS_5.10|libaio.so.1|__libaio_pwrite
+SCOPED_SYMBOL|SunOS_5.10|libaio.so.1|__libaio_read
+SCOPED_SYMBOL|SunOS_5.10|libaio.so.1|__libaio_write
+SCOPED_SYMBOL|SunOS_5.8|libbsm.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.8|libbsm.so.1|auditstat
+SCOPED_SYMBOL|SunOS_5.8|libbsm.so.1|audituser
+SCOPED_SYMBOL|SunOS_5.8|libbsm.so.1|getkernstate
+SCOPED_SYMBOL|SunOS_5.8|libbsm.so.1|getuseraudit
+SCOPED_SYMBOL|SunOS_5.8|libbsm.so.1|setkernstate
+SCOPED_SYMBOL|SunOS_5.8|libbsm.so.1|setuseraudit
+SCOPED_SYMBOL|SunOS_5.8|libbsm.so.1|audit_cron_make_anc_name
+SCOPED_SYMBOL|SunOS_5.8|libbsm.so.1|audit_init_generic
+SCOPED_SYMBOL|SunOS_5.8|libbsm.so.1|audit_shutdown_generic
+SCOPED_SYMBOL|SunOS_5.8|libbsm.so.1|audit_uadmin_fail
+SCOPED_SYMBOL|SunOS_5.8|libbsm.so.1|bsm_dom
+SCOPED_SYMBOL|SunOS_5.9|libc.so.1|_thr_libthread
+SCOPED_SYMBOL|SunOS_5.9|libc.so.1|_libc_child_atfork
+SCOPED_SYMBOL|SunOS_5.9|libc.so.1|_libc_parent_atfork
+SCOPED_SYMBOL|SunOS_5.9|libc.so.1|_libc_prepare_atfork
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|___lwp_cond_wait
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|___lwp_mutex_lock
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|__lwp_create
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|__lwp_exit
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|__lwp_getprivate
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|__lwp_makecontext
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|__lwp_setprivate
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|__lwp_wait
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|__sigaction
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_lwp_create
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_lwp_exit
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_lwp_getprivate
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_lwp_makecontext
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_lwp_setprivate
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_lwp_wait
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_thr_errnop
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|___lwp_mutex_unlock
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|thr_errnop
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|__lwp_sigredirect
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|__signotifywait
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_lwp_sigredirect
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_signotifywait
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|__mt_sigpending
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_libc_nanosleep
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_libc_sigprocmask
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_libc_sigtimedwait
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_libc_threads_interface
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|__lwp_schedctl
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|__lwp_suspend2
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_lwp_schedctl
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_lwp_suspend2
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|___lwp_mutex_trylock
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|___lwp_mutex_wakeup
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|___xpg4_putmsg
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|___xpg4_putpmsg
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|__lwp_sigtimedwait
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_libc_tsd_common
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_lwp_sigtimedwait
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|__lwp_detach
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|__setcontext
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_lpostfork_child_handler
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_lpostfork_parent_handler
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_lprefork_handler
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_lpthread_atfork
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_lwp_detach
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_postfork_child_handler
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_postfork_parent_handler
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_prefork_handler
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_register_forkhandler
+SCOPED_SYMBOL|SunOS_5.10|libc.so.1|_unregister_forkhandler
+SCOPED_SYMBOL|SunOS_5.9|libnsl.so.1|_exec_checkid
+SCOPED_SYMBOL|SunOS_5.9|libthread.so.1|_thr_libthread
+SCOPED_SYMBOL|SunOS_5.9|libthread.so.1|thr_slot_get
+SCOPED_SYMBOL|SunOS_5.9|libthread.so.1|thr_slot_set
+SCOPED_SYMBOL|SunOS_5.9|libthread.so.1|thr_slot_sync_allocate
+SCOPED_SYMBOL|SunOS_5.9|libthread.so.1|thr_slot_sync_deallocate
+SCOPED_SYMBOL|SunOS_5.10|libthread.so.1|_thr_errnop
+SCOPED_SYMBOL|SunOS_5.10|libthread.so.1|_cond_timedwait_cancel
+SCOPED_SYMBOL|SunOS_5.10|libthread.so.1|_cond_wait_cancel
+SCOPED_SYMBOL|SunOS_5.10|libthread.so.1|_sema_wait_cancel
+SCOPED_SYMBOL|SunOS_5.10|libthread.so.1|_libthread_sema_wait
+SCOPED_SYMBOL|SunOS_5.9|libX11.so.4|_X11TransDNIAddr
+SCOPED_SYMBOL|SunOS_5.9|libX11.so.4|_X11TransDNIFuncs
+SCOPED_SYMBOL|SunOS_5.9|libX11.so.4|_X11TransDNIGetHostByAddr
+SCOPED_SYMBOL|SunOS_5.9|libX11.so.4|_X11TransDNIGetHostByName
+SCOPED_SYMBOL|SunOS_5.9|libX11.so.4|_X11TransDNIGetHostName
+SCOPED_SYMBOL|SunOS_5.9|libX11.so.4|_X11TransDNIInit
+SCOPED_SYMBOL|SunOS_5.9|libX11.so.4|_X11TransDNIntoa
+SCOPED_SYMBOL|SunOS_5.9|libX11.so.4|_XimXTransDNIAddr
+SCOPED_SYMBOL|SunOS_5.9|libX11.so.4|_XimXTransDNIFuncs
+SCOPED_SYMBOL|SunOS_5.9|libX11.so.4|_XimXTransDNIGetHostByAddr
+SCOPED_SYMBOL|SunOS_5.9|libX11.so.4|_XimXTransDNIGetHostByName
+SCOPED_SYMBOL|SunOS_5.9|libX11.so.4|_XimXTransDNIGetHostName
+SCOPED_SYMBOL|SunOS_5.9|libX11.so.4|_XimXTransDNIInit
+SCOPED_SYMBOL|SunOS_5.9|libX11.so.4|_XimXTransDNIntoa
+SCOPED_SYMBOL|SunOS_5.9|libpthread.so.1|_pthread_mutex_attr_gettype
+SCOPED_SYMBOL|SunOS_5.9|libpthread.so.1|_pthread_mutex_attr_settype
+SCOPED_SYMBOL|SunOS_5.9|libpthread.so.1|pthread_mutex_attr_gettype
+SCOPED_SYMBOL|SunOS_5.9|libpthread.so.1|pthread_mutex_attr_settype
+SCOPED_SYMBOL|SunOS_5.10|libpthread.so.1|_libthread_sema_wait
+SCOPED_SYMBOL|SunOS_5.8|libdevinfo.so.1|devfs_find
+SCOPED_SYMBOL|SunOS_5.8|libdevinfo.so.1|devfs_find_all
+SCOPED_SYMBOL|SunOS_5.8|libdevinfo.so.1|devfs_is_nexus_driver
+SCOPED_SYMBOL|SunOS_5.8|libdevinfo.so.1|devfs_iscbdriver
+SCOPED_SYMBOL|SunOS_5.8|libdevinfo.so.1|devinfo_prop_get_int
+SCOPED_SYMBOL|SunOS_5.8|libdevinfo.so.1|local_addr
+SCOPED_SYMBOL|SunOS_5.10|libdevinfo.so.1|di_devlink_synchronize_db
+SCOPED_SYMBOL|SunOS_5.8|libdmi.so.1|trace_on
+SCOPED_SYMBOL|SunOS_5.8|libdmi.so.1|get_debug_flag
+SCOPED_SYMBOL|SunOS_5.8|libdmi.so.1|set_debug_flag
+SCOPED_SYMBOL|SunOS_5.8|libprint.so.2|dynamic_function
+SCOPED_SYMBOL|SunOS_5.8|libprint.so.2|etc_get_list
+SCOPED_SYMBOL|SunOS_5.8|libprint.so.2|etc_get_name
+SCOPED_SYMBOL|SunOS_5.8|libprint.so.2|etc_put_printer
+SCOPED_SYMBOL|SunOS_5.8|libprint.so.2|nis_get_list
+SCOPED_SYMBOL|SunOS_5.8|libprint.so.2|nis_get_name
+SCOPED_SYMBOL|SunOS_5.8|libprint.so.2|nisplus_get_list
+SCOPED_SYMBOL|SunOS_5.8|libprint.so.2|nisplus_get_name
+SCOPED_SYMBOL|SunOS_5.8|libprint.so.2|posix_name
+SCOPED_SYMBOL|SunOS_5.8|libprint.so.2|user_get_list
+SCOPED_SYMBOL|SunOS_5.8|libprint.so.2|user_get_name
+SCOPED_SYMBOL|SunOS_5.8|libprint.so.2|user_put_printer
+SCOPED_SYMBOL|SunOS_5.8|libprint.so.2|xfn_get_list
+SCOPED_SYMBOL|SunOS_5.8|libprint.so.2|xfn_get_name
+SCOPED_SYMBOL|SunOS_5.10|libprint.so.2|xfn_put_printer
+SCOPED_SYMBOL|SunOS_5.9|libresolv.so.2|evPollfdAdd
+SCOPED_SYMBOL|SunOS_5.9|libresolv.so.2|evPollfdDel
+SCOPED_SYMBOL|SunOS_5.10|libXm.so.4|Xm21GetPixmapByDepth
+SCOPED_SYMBOL|SunOS_5.10|libXm.so.4|Xm21InstallImage
+SCOPED_SYMBOL|SunOS_5.10|libXm.so.4|Xm21UninstallImage
+SCOPED_SYMBOL|SunOS_5.10|libXm.so.4|_Xm21GetPixmapData
+SCOPED_SYMBOL|SunOS_5.10|libXm.so.4|_Xm21InstallImage
+SCOPED_SYMBOL|SunOS_5.8|libpam.so.1|_lib_version
+SCOPED_SYMBOL|SunOS_5.8|libproc.so.1|proc_addr_to_map
+SCOPED_SYMBOL|SunOS_5.8|libproc.so.1|proc_execname
+SCOPED_SYMBOL|SunOS_5.8|libproc.so.1|proc_getenv
+SCOPED_SYMBOL|SunOS_5.8|libproc.so.1|proc_lookup_by_addr
+SCOPED_SYMBOL|SunOS_5.8|libproc.so.1|proc_lookup_by_name
+SCOPED_SYMBOL|SunOS_5.8|libproc.so.1|proc_lwp_iter
+SCOPED_SYMBOL|SunOS_5.8|libproc.so.1|proc_mapping_iter
+SCOPED_SYMBOL|SunOS_5.8|libproc.so.1|proc_object_iter
+SCOPED_SYMBOL|SunOS_5.8|libproc.so.1|proc_objname
+SCOPED_SYMBOL|SunOS_5.8|libproc.so.1|proc_pidarg
+SCOPED_SYMBOL|SunOS_5.8|libproc.so.1|proc_rd_agent
+SCOPED_SYMBOL|SunOS_5.8|libproc.so.1|proc_read_string
+SCOPED_SYMBOL|SunOS_5.8|libproc.so.1|proc_reset_maps
+SCOPED_SYMBOL|SunOS_5.8|libproc.so.1|proc_stack_iter
+SCOPED_SYMBOL|SunOS_5.8|libproc.so.1|proc_symbol_iter
+SCOPED_SYMBOL|SunOS_5.8|libproc.so.1|proc_update_maps
+SCOPED_SYMBOL|SunOS_5.10|libproc.so.1|Plookup_by_lmid
+SCOPED_SYMBOL|SunOS_5.8|libssagent.so.1|SSAAutoMemFree
+SCOPED_SYMBOL|SunOS_5.8|libssagent.so.1|SSARegSubtable
+SCOPED_SYMBOL|SunOS_5.9|libICE.so.6|CheckDNIName
+SCOPED_SYMBOL|SunOS_5.9|libICE.so.6|DNIEnabled
+SCOPED_SYMBOL|SunOS_5.9|libICE.so.6|GetTransCount
+SCOPED_SYMBOL|SunOS_5.9|libICE.so.6|_IceTransDNIAddr
+SCOPED_SYMBOL|SunOS_5.9|libICE.so.6|_IceTransDNIFuncs
+SCOPED_SYMBOL|SunOS_5.9|libICE.so.6|_IceTransDNIGetHostByAddr
+SCOPED_SYMBOL|SunOS_5.9|libICE.so.6|_IceTransDNIGetHostByName
+SCOPED_SYMBOL|SunOS_5.9|libICE.so.6|_IceTransDNIGetHostName
+SCOPED_SYMBOL|SunOS_5.9|libICE.so.6|_IceTransDNIInit
+SCOPED_SYMBOL|SunOS_5.9|libICE.so.6|_IceTransDNIntoa
+SCOPED_SYMBOL|SunOS_5.9|librcm.so.1|se_alloc
+SCOPED_SYMBOL|SunOS_5.9|librcm.so.1|se_append_bytes
+SCOPED_SYMBOL|SunOS_5.9|librcm.so.1|se_append_ints
+SCOPED_SYMBOL|SunOS_5.9|librcm.so.1|se_append_strings
+SCOPED_SYMBOL|SunOS_5.9|librcm.so.1|se_end_of_data
+SCOPED_SYMBOL|SunOS_5.9|librcm.so.1|se_free
+SCOPED_SYMBOL|SunOS_5.9|librcm.so.1|se_get_next_tuple
+SCOPED_SYMBOL|SunOS_5.9|librcm.so.1|se_lookup_bytes
+SCOPED_SYMBOL|SunOS_5.9|librcm.so.1|se_lookup_ints
+SCOPED_SYMBOL|SunOS_5.9|librcm.so.1|se_lookup_strings
+SCOPED_SYMBOL|SunOS_5.9|librcm.so.1|se_tuple_bytes
+SCOPED_SYMBOL|SunOS_5.9|librcm.so.1|se_tuple_ints
+SCOPED_SYMBOL|SunOS_5.9|librcm.so.1|se_tuple_name
+SCOPED_SYMBOL|SunOS_5.9|librcm.so.1|se_tuple_strings
+SCOPED_SYMBOL|SunOS_5.9|librcm.so.1|se_tuple_type
+SCOPED_SYMBOL|SunOS_5.9|libsldap.so.1|__ns_ldap_cache_destroy
+SCOPED_SYMBOL|SunOS_5.9|libsldap.so.1|__ns_ldap_dump_profile
+SCOPED_SYMBOL|SunOS_5.9|libsldap.so.1|__ns_ldap_freeAuth
+SCOPED_SYMBOL|SunOS_5.10|libsmartcard.so.1|OCF_ListReadersPresent
+SCOPED_SYMBOL|SunOS_5.6|libX11.so.4|XauGetAuthByAddr
diff --git a/usr/src/cmd/abi/appcert/etc/etc.tweaks.in b/usr/src/cmd/abi/appcert/etc/etc.tweaks.in
new file mode 100644
index 0000000..e6c8470
--- /dev/null
+++ b/usr/src/cmd/abi/appcert/etc/etc.tweaks.in
@@ -0,0 +1,355 @@
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# 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
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+#
+# Special Cases Database. Model Tweaks.
+#
+# Format: MODEL_TWEAK|<library>|<arch1,...>|<symbol>|<classification>
+#
+# if <arch> is "*" applies to all arches.
+# <classification> is "public" or "private"
+#
+
+MODEL_TWEAK|/usr/lib/libnsl.so.1|*|gethostname|public
+MODEL_TWEAK|/usr/lib/libc.so.1|*|mkstemp|public
+# /usr/openwin/include/X11/Xlibint.h possible macros, etc.
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XAllocScratch|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XAllocTemp|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XAsyncErrorHandler|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_Xdebug|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XDeq|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XEatData|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XEnq|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XError|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XErrorFunction|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XEventsQueued|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XFlush|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XFreeTemp|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XGetAsyncReply|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XGetHostname|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XIOError|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XIOErrorFunction|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XRead|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XReadEvents|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XReadPad|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XRegisterInternalConnection|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XReply|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XScreenOfWindow|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XSend|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XSetLastRequestRead|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XUnregisterInternalConnection|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XVIDtoVisual|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_Xglobal_lock|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|XReadBitmapFileData|unclassified
+#
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtStrings|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtShellStrings|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|_XtInheritTranslations|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|_XtIsSubclassOf|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|_XtCheckSubclassFlag|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|_XUnlockMutex_fn|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|_XLockMutex_fn|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtSetSelectionParameters|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtSendSelectionRequest|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtGetSelectionParameters|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtR6ShellStrings|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtOpenApplication|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|_XtInherit|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtR6Strings|unclassified
+#
+MODEL_TWEAK|/usr/openwin/lib/libXm.so.3|*|_XmInheritClass|unclassified
+MODEL_TWEAK|/usr/lib/libc.so.1|*|thr_main|public
+#
+MODEL_TWEAK|/usr/lib/libc.so.1|i386,amd64|htonl|public
+MODEL_TWEAK|/usr/lib/libc.so.1|i386,amd64|htons|public
+MODEL_TWEAK|/usr/lib/libc.so.1|i386,amd64|ntohl|public
+MODEL_TWEAK|/usr/lib/libc.so.1|i386,amd64|ntohs|public
+MODEL_TWEAK|/usr/lib/libc.so.1|*|__trans_lower|public
+MODEL_TWEAK|/usr/lib/libc.so.1|*|__trans_upper|public
+MODEL_TWEAK|/usr/lib/libdmi.so.1|*|dmi_error|public
+MODEL_TWEAK|/usr/lib/libdmi.so.1|*|freeDmiString|public
+MODEL_TWEAK|/usr/lib/libdmi.so.1|*|newDmiString|public
+MODEL_TWEAK|/usr/lib/libdmi.so.1|*|printDmiDataUnion|public
+MODEL_TWEAK|/usr/lib/libdmi.so.1|*|printDmiString|public
+MODEL_TWEAK|/usr/lib/libresolv.so.2|*|res_mkupdrec|public
+MODEL_TWEAK|/usr/lib/libresolv.so.2|*|__p_rr|private
+MODEL_TWEAK|/usr/dt/lib/libDtSvc.so.1|*|DtActionInvoke|public
+MODEL_TWEAK|/usr/dt/lib/libDtSvc.so.1|*|DtCreateHelpDialog|public
+MODEL_TWEAK|/usr/dt/lib/libDtSvc.so.1|*|DtCreateHelpQuickDialog|public
+MODEL_TWEAK|/usr/dt/lib/libDtSvc.so.1|*|DtDtsIsTrue|public
+MODEL_TWEAK|/usr/dt/lib/libDtSvc.so.1|*|DtHelpQuickDialogGetChild|public
+MODEL_TWEAK|/usr/dt/lib/libDtSvc.so.1|*|DtHelpReturnSelectedWidgetId|public
+MODEL_TWEAK|/usr/dt/lib/libDtSvc.so.1|*|DtSaverGetWindows|public
+MODEL_TWEAK|/usr/dt/lib/libDtSvc.so.1|*|DtWsmRemoveWorkspaceCallback|public
+#
+MODEL_TWEAK|/usr/dt/lib/libXm.so.4|*|_XmStrings|unclassified
+MODEL_TWEAK|/usr/dt/lib/libXm.so.4|*|_XmStrings21|unclassified
+#
+MODEL_TWEAK|/usr/openwin/lib/libXaw.so.5|*|FMT8BIT|unclassified
+#
+# These special symbols are well-known, e.g. crt, and uninteresting.
+SKIP_SYMBOL|_END_
+SKIP_SYMBOL|_START_
+SKIP_SYMBOL|__1cG__CrunMdo_exit_code6F_v_
+SKIP_SYMBOL|__1cG__CrunVdo_exit_code_in_range6Fpv1_v_
+SKIP_SYMBOL|__1cH__CimplKcplus_fini6F_v_
+SKIP_SYMBOL|__1cH__CimplKcplus_init6F_v_
+SKIP_SYMBOL|__fsr_init_value
+SKIP_SYMBOL|_ex_deregister
+SKIP_SYMBOL|_ex_register
+SKIP_SYMBOL|_fini
+SKIP_SYMBOL|_get_exit_frame_monitor
+SKIP_SYMBOL|_init
+SKIP_SYMBOL|_objcInit
+SKIP_SYMBOL|main
+SKIP_SYMBOL|_ctype
+SKIP_SYMBOL|__ctype
+SKIP_SYMBOL|__ctype_mask
+SKIP_SYMBOL|_end
+SKIP_SYMBOL|_environ
+SKIP_SYMBOL|environ
+SKIP_SYMBOL|errno
+SKIP_SYMBOL|__iob
+SKIP_SYMBOL|_lib_version
+#
+MODEL_TWEAK=5.5.1|/usr/lib/libthread.so.1|*|kill|public
+#
+# UNIX98 project
+SKIP_SYMBOL|__fgetwc_xpg5
+SKIP_SYMBOL|__fgetws_xpg5
+SKIP_SYMBOL|__fputwc_xpg5
+SKIP_SYMBOL|__fputws_xpg5
+SKIP_SYMBOL|__getwc_xpg5
+SKIP_SYMBOL|__getwchar_xpg5
+SKIP_SYMBOL|__putwc_xpg5
+SKIP_SYMBOL|__putwchar_xpg5
+SKIP_SYMBOL|__ungetwc_xpg5
+SKIP_SYMBOL|__wcsftime_xpg5
+SKIP_SYMBOL|__wcstok_xpg5
+#
+# C99 complex arithmetic functions
+# sparc, sparcv9, i386
+SKIP_SYMBOL|_F_cplx_mul
+SKIP_SYMBOL|_F_cplx_div
+SKIP_SYMBOL|_F_cplx_div_rx
+SKIP_SYMBOL|_F_cplx_div_ix
+SKIP_SYMBOL|_D_cplx_mul
+SKIP_SYMBOL|_D_cplx_div
+SKIP_SYMBOL|_D_cplx_div_rx
+SKIP_SYMBOL|_D_cplx_div_ix
+# sparc, sparcv9
+SKIP_SYMBOL|_Q_cplx_mul
+SKIP_SYMBOL|_Q_cplx_div
+SKIP_SYMBOL|_Q_cplx_div_rx
+SKIP_SYMBOL|_Q_cplx_div_ix
+SKIP_SYMBOL|_Q_cplx_lr_mul
+SKIP_SYMBOL|_Q_cplx_lr_div
+SKIP_SYMBOL|_Q_cplx_lr_div_rx
+SKIP_SYMBOL|_Q_cplx_lr_div_ix
+# i386
+SKIP_SYMBOL|_F_cplx_lr_div
+SKIP_SYMBOL|_F_cplx_lr_div_rx
+SKIP_SYMBOL|_F_cplx_lr_div_ix
+SKIP_SYMBOL|_D_cplx_lr_div
+SKIP_SYMBOL|_D_cplx_lr_div_rx
+SKIP_SYMBOL|_D_cplx_lr_div_ix
+SKIP_SYMBOL|_X_cplx_mul
+SKIP_SYMBOL|_X_cplx_div
+SKIP_SYMBOL|_X_cplx_div_rx
+SKIP_SYMBOL|_X_cplx_div_ix
+SKIP_SYMBOL|_X_cplx_lr_div
+SKIP_SYMBOL|_X_cplx_lr_div_rx
+SKIP_SYMBOL|_X_cplx_lr_div_ix
+#
+# UNIX03 compiler generated
+# Printing functions:
+SKIP_SYMBOL|_fprintf_c89
+SKIP_SYMBOL|_printf_c89
+SKIP_SYMBOL|_snprintf_c89
+SKIP_SYMBOL|_sprintf_c89
+SKIP_SYMBOL|_vfprintf_c89
+SKIP_SYMBOL|_vprintf_c89
+SKIP_SYMBOL|_vsnprintf_c89
+SKIP_SYMBOL|_vsprintf_c89
+SKIP_SYMBOL|_fwprintf_c89
+SKIP_SYMBOL|_swprintf_c89
+SKIP_SYMBOL|_wprintf_c89
+SKIP_SYMBOL|_vfwprintf_c89
+SKIP_SYMBOL|_vswprintf_c89
+SKIP_SYMBOL|_vwprintf_c89
+SKIP_SYMBOL|_wsprintf_c89
+# Scanning functions:
+SKIP_SYMBOL|_fscanf_c89
+SKIP_SYMBOL|_scanf_c89
+SKIP_SYMBOL|_sscanf_c89
+SKIP_SYMBOL|_vfscanf_c89
+SKIP_SYMBOL|_vscanf_c89
+SKIP_SYMBOL|_vsscanf_c89
+SKIP_SYMBOL|_fwscanf_c89
+SKIP_SYMBOL|_swscanf_c89
+SKIP_SYMBOL|_wscanf_c89
+SKIP_SYMBOL|_vfwscanf_c89
+SKIP_SYMBOL|_vswscanf_c89
+SKIP_SYMBOL|_vwscanf_c89
+SKIP_SYMBOL|_wsscanf_c89
+#
+SKIP_SYMBOL|_imaxabs_c89
+SKIP_SYMBOL|_imaxdiv_c89
+SKIP_SYMBOL|_strtoimax_c89
+SKIP_SYMBOL|_strtoumax_c89
+SKIP_SYMBOL|_wcstoimax_c89
+SKIP_SYMBOL|_wcstoumax_c89
+SKIP_SYMBOL|__assert_c99
+SKIP_SYMBOL|_imaxabs_c89
+SKIP_SYMBOL|_imaxdiv_c89
+#
+SKIP_SYMBOL|_QgetRD
+SKIP_SYMBOL|_QgetRP
+SKIP_SYMBOL|_QswapRD
+SKIP_SYMBOL|_QswapRP
+SKIP_SYMBOL|__divrem64
+SKIP_SYMBOL|__divdi3
+SKIP_SYMBOL|__muldi3
+SKIP_SYMBOL|__moddi3
+SKIP_SYMBOL|__udivdi3
+SKIP_SYMBOL|__umoddi3
+SKIP_SYMBOL|__cmpdi2
+SKIP_SYMBOL|__ucmpdi2
+SKIP_SYMBOL|__floatdidf
+SKIP_SYMBOL|__floatdisf
+SKIP_SYMBOL|__ashldi3
+SKIP_SYMBOL|__ashrdi3
+SKIP_SYMBOL|__lshrdi3
+SKIP_SYMBOL|__fltrounds
+SKIP_SYMBOL|_fpsetsticky
+SKIP_SYMBOL|_fpsetround
+SKIP_SYMBOL|_finite
+SKIP_SYMBOL|_getfp
+SKIP_SYMBOL|__swapEX
+SKIP_SYMBOL|__swapRD
+SKIP_SYMBOL|__swapTE
+SKIP_SYMBOL|__udivrem64
+SKIP_SYMBOL|__xgetRD
+SKIP_SYMBOL|__xtol
+SKIP_SYMBOL|__xtoll
+SKIP_SYMBOL|__xtoul
+SKIP_SYMBOL|__xtoull
+#
+MODEL_TWEAK|/usr/openwin/lib/libdpstk.so.5|*|XDPSCreatePixmapForEPSF|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libdpstk.so.5|*|XDPSImageFileIntoDrawable|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libdpstk.so.5|*|XDPSPixelsPerPoint|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libICE.so.6|*|_IceRead|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libICE.so.6|*|_IceWrite|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|XConvertCase|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|XESetEventToWire|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|XESetWireToEvent|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XFlushGCCache|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|XInternalConnectionNumbers|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|XProcessInternalConnection|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|XauDisposeAuth|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|XauReadAuth|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|XtCvtStringToFont|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|XAddConnectionWatch|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXaw.so.5|*|XawInitializeWidgetSet|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXaw.so.5|*|XawViewportSetCoordinates|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXaw.so.5|*|XawTextSinkSetTabs|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtAppLock|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtAppUnlock|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtCvtStringToFontSet|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtCvtStringToFontStruct|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtProcessLock|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtProcessUnlock|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtSetEventDispatcher|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtRegisterExtensionSelector|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtToolkitThreadInitialize|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtGetClassExtension|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|colorConvertArgs|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtRegisterDrawable|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtSessionReturnToken|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtAppSetExitFlag|unclassified
+MODEL_TWEAK|/usr/lib/libcurses.so.1|*|stdscr|unclassified
+MODEL_TWEAK|/usr/lib/libcurses.so.1|*|COLS|unclassified
+MODEL_TWEAK|/usr/lib/libcurses.so.1|*|LINES|unclassified
+MODEL_TWEAK|/usr/lib/libcurses.so.1|*|curscr|unclassified
+#
+MODEL_TWEAK|/usr/dt/lib/libXm.so.3|*|_XmInheritClass|unclassified
+MODEL_TWEAK|/usr/dt/lib/libtt.so.2|*|Tttk_string|unclassified
+MODEL_TWEAK|/usr/dt/lib/libXm.so.4|*|XmStringCreateLtoR|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|XauGetBestAuthByAddr|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|XInitExtension|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|XAddExtension|unclassified
+MODEL_TWEAK|/usr/dt/lib/libXm.so.4|*|XmStringCreateSimple|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtUnregisterDrawable|unclassified
+#
+MODEL_TWEAK|/usr/lib/ld.so.1|*|dladdr1|public
+MODEL_TWEAK|/usr/lib/ld.so.1|*|dlmopen|public
+MODEL_TWEAK|/usr/lib/ld.so.1|*|dldump|public
+MODEL_TWEAK|/usr/lib/ld.so.1|*|dlinfo|public
+MODEL_TWEAK|/usr/lib/ld.so.1|*|dladdr|public
+MODEL_TWEAK|/usr/lib/ld.so.1|*|dlopen|public
+MODEL_TWEAK|/usr/lib/ld.so.1|*|dlsym|public
+MODEL_TWEAK|/usr/lib/ld.so.1|*|dlerror|public
+MODEL_TWEAK|/usr/lib/ld.so.1|*|dlclose|public
+#
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtCvtStringToPixel|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXt.so.4|*|XtCvtStringToBoolean|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libXext.so.0|*|XScreenSaverAllocInfo|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|XLockDisplay|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|XUnlockDisplay|unclassified
+MODEL_TWEAK|/usr/openwin/lib/libX11.so.4|*|_XInitImageFuncPtrs|unclassified
+MODEL_TWEAK|/usr/lib/libnsl.so.1|*|t_errlist|unclassified
+#
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__w1|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_HLINE|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_VLINE|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_BLOCK|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_BOARD|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_BTEE|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_BULLET|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_CKBOARD|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_DARROW|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_DEGREE|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_DIAMOND|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_LANTERN|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_LARROW|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_LLCORNER|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_LRCORNER|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_LTEE|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_PLMINUS|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_PLUS|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_RARROW|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_RTEE|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_S1|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_S9|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_TTEE|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_UARROW|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_ULCORNER|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__WACS_URCORNER|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__cht1|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__cht2|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__pcht1|public
+MODEL_TWEAK|/usr/xpg4/lib/libcurses.so.2|*|__pcht2|public
diff --git a/usr/src/cmd/abi/appcert/etc/etc.warn.in b/usr/src/cmd/abi/appcert/etc/etc.warn.in
new file mode 100644
index 0000000..d78ffb5
--- /dev/null
+++ b/usr/src/cmd/abi/appcert/etc/etc.warn.in
@@ -0,0 +1,91 @@
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# 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
+#
+# syntax:
+#WARNING:<label>:<1-line-desc>:<lib>|<sym>|<caller>,...:<text>
+# or
+#WARNING:<label>:<1-line-desc>:MATCH <expression>:<text>
+#
+# the label's and 1-line-desc's must be unique.
+# the warning matches if any of the <lib>|<sym>|<caller> in the
+# comma separated list match.
+# "\" may be used to continue a line. the newline is replaced by " ".
+# Another way to quote a block of text is to sandwich it between
+# single "-". The newline previous to the 1st "-" must be "\" quoted.
+# Special keywords in <expression>:
+# file =~ -> $file =~ where $file is `/bin/file /path/to/object`
+# dump =~ -> $dump =~ where $dump is `/usr/ccs/bin/dump /path/to/object`
+# needed =~ -> $needed =~ where $needed is a list of all ldd needed libs.
+# syms =~ -> $syms =~ where $syms is a string of the direct symbols.
+#
+# Note: if <lib> is a full path (contains /) that symlinks are not
+# automatically handled (as they are for the models and the tweaks), so
+# you have to list all likely symbolic links in the check (see ptrace ex.)
+#
+###############################################################################
+WARNING:sys_errlist:gettext("references sys_errlist/sys_nerr"):libc.so.1|sys_errlist|*DIRECT*,libc.so.1|sys_nerr|*DIRECT*:
+###############################################################################
+WARNING:libkvm:gettext("calls libkvm kernel interfaces"):libkvm.so.1|*|*DIRECT*:
+###############################################################################
+WARNING:libproc:gettext("calls libproc interfaces"):libproc.so.1|*|*DIRECT*:
+###############################################################################
+WARNING:libxgl:gettext("calls libxgl graphics library"):libxgl.so.3|*|*DIRECT*:
+###############################################################################
+WARNING:libxil:gettext("calls libxil imaging library"):libxil.so.1|*|*DIRECT*:
+###############################################################################
+WARNING:libkrb:gettext("calls libkrb kerberos library"):libkrb.so.1|*|*DIRECT*:
+###############################################################################
+WARNING:libauth:gettext("calls libauth library"):libauth.so.1|*|*DIRECT*:
+###############################################################################
+WARNING:libdevfsevent:gettext("calls libdevfsevent library"):libdevfsevent.so.1|*|*DIRECT*:
+###############################################################################
+WARNING:libdhcp:gettext("calls libdhcp.so.2 library"):libdhcp.so.2|*|*DIRECT*:
+###############################################################################
+WARNING:libami:gettext("calls libami library"):libami.so.1|*|*DIRECT*,libami-global.so.1|*|*DIRECT*:
+###############################################################################
+WARNING:ALT_USAGE _XtwaitForSomething:gettext("calls incompatible _XtwaitForSomething"):libXt.so.*|_XtwaitForSomething|*DIRECT*:
+###############################################################################
+WARNING:sunos4x:gettext("SunOS 4.x a.out binary"):MATCH file=~/Sun demand paged|pure SPARC/:
+###############################################################################
+WARNING:fork1_forkall:gettext("non-POSIX libthread fork call"):MATCH dump=~/NEEDED\s*libthread\.so\.1/ && !(needed=~/libpthread\.so\.1/) && syms=~/\b(fork|_fork)\b/:
+###############################################################################
+WARNING:sysmem:gettext("calls deprecated sysmem/asysmem"):libadm.so.1|sysmem|*DIRECT*,libadm.so.1|asysmem|*DIRECT*:
+###############################################################################
+WARNING:_lwp_create:gettext("uses lightweight processes directly"):libc.so.1|_lwp_create|*DIRECT*,libc.so.1|_lwp_detach|*DIRECT*,libc.so.1|_lwp_exit|*DIRECT*,libc.so.1|_lwp_getprivate|*DIRECT*,libc.so.1|_lwp_makecontext|*DIRECT*,libc.so.1|_lwp_setprivate|*DIRECT*,libc.so.1|_lwp_wait|*DIRECT*:
+###############################################################################
+WARNING:libldap.so.3:gettext("calls obsolete LDAP library libldap.so.3"):libldap.so.3|*|*DIRECT*:
+###############################################################################
+WARNING:libxfn:gettext("calls obsolete federated naming library libxfn.so"):libxfn.so.1|*|*DIRECT*,libxfn.so.2|*|*DIRECT*:
+###############################################################################
+WARNING:auditsvc:gettext("calls libbsm interface auditsvc(2)"):libbsm.so.1|auditsvc|*DIRECT*:
+###############################################################################
+WARNING:libXinput:gettext("calls obsolete input library libXinput.so.0"):libXinput.so.0|*|*DIRECT*:
+###############################################################################
+WARNING:libkcs:gettext("calls KCMS library libkcs.so.1"):libkcs.so.1|*|*DIRECT*:
+###############################################################################
+WARNING:64-bit-ptrace:gettext("calls 64-bit ptrace(2) interface"):/usr/lib/sparcv9/libc.so.1|ptrace|*DIRECT*,/usr/lib/64/libc.so.1|ptrace|*DIRECT*:
+###############################################################################
+WARNING:makecontext:gettext("possible makecontext(3C) source incompatibility"):libc.so.1|makecontext|*DIRECT*:
diff --git a/usr/src/cmd/abi/appcert/scripts/AppcertUtil.pm b/usr/src/cmd/abi/appcert/scripts/AppcertUtil.pm
new file mode 100644
index 0000000..4eba2fb
--- /dev/null
+++ b/usr/src/cmd/abi/appcert/scripts/AppcertUtil.pm
@@ -0,0 +1,1951 @@
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# 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
+#
+
+#
+# This module contains utility routines and data for use by the appcert
+# programs: appcert, symprof, symcheck, and symreport.
+#
+
+package AppcertUtil;
+
+require 5.005;
+use strict;
+use locale;
+use Getopt::Std;
+use POSIX qw(locale_h);
+use Sun::Solaris::Utils qw(textdomain gettext);
+use File::Basename;
+use File::Path;
+
+BEGIN {
+ use Exporter();
+ use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
+
+ @ISA = qw(Exporter);
+ @EXPORT = qw(
+ $command_name
+ $object_dir
+ $solaris_library_ld_path
+ $uname_p
+ $working_dir
+ $appcert_lib_dir
+ $batch_report
+ $binary_count
+ $block_min
+ $block_max
+ $tmp_dir
+
+ $cmd_dump
+ $cmd_elfdump
+ $cmd_file
+ $cmd_find
+ $cmd_ldd
+ $cmd_ls
+ $cmd_more
+ $cmd_pvs
+ $cmd_sort
+ $cmd_uname
+ $cmd_uniq
+
+ @lib_index_loaded
+
+ %lib_index_definition
+ %text
+ %model_tweak
+ %skip_symbols
+ %scoped_symbol
+ %scoped_symbol_all
+ %warnings_bind
+ %warnings_desc
+ %warnings_match
+
+ &object_to_dir_name
+ &dir_name_to_path
+ &next_dir_name
+ &cmd_output_file
+ &cmd_output_dump
+ &all_ldd_neededs
+ &all_ldd_neededs_string
+ &direct_syms
+ &import_vars_from_environment
+ &export_vars_to_environment
+ &c_locale
+ &overall_result_code
+ &trim
+ &sort_on_count
+ &print_line
+ &list_format
+ &emsg
+ &pmsg
+ &nofile
+ &nopathexist
+ &norunprog
+ &nocreatedir
+ &exiter
+ &set_clean_up_exit_routine
+ &signals
+ &create_tmp_dir
+ &dir_is_empty
+ &follow_symlink
+ &is_statically_linked
+ &is_elf
+ &is_shared_object
+ &is_aout
+ &is_suid
+ &bin_type
+ &files_equal
+ &purge_caches
+ &filter_lib_type
+ &load_model_index
+ &load_misc_check_databases
+ );
+
+ @EXPORT_OK = ();
+
+ %EXPORT_TAGS = ();
+}
+
+use vars @EXPORT;
+use vars @EXPORT_OK;
+
+use vars qw(
+ $lib_match_initialized
+
+ %lib_index
+ %lib_index_loaded
+ %shared_object_index
+
+ %file_inode_cache
+ %file_exists_cache
+ %filter_lib_cache
+ %lib_match_cache
+ %cmd_output_file_cache
+ %cmd_output_dump_cache
+ %all_ldd_neededs_cache
+);
+
+my $clean_up_exit_routine;
+my $tmp_dir_count = 0;
+my $next_dir_name_dh;
+my $LC_ALL = '';
+
+# Get the name of the program:
+$command_name = basename($0);
+
+$cmd_dump = '/usr/ccs/bin/dump';
+$cmd_elfdump = '/usr/ccs/bin/elfdump';
+$cmd_file = '/usr/bin/file';
+$cmd_find = '/usr/bin/find';
+$cmd_ldd = '/usr/bin/ldd';
+$cmd_ls = '/usr/bin/ls';
+$cmd_more = '/usr/bin/more';
+$cmd_pvs = '/usr/bin/pvs';
+$cmd_sort = '/usr/bin/sort';
+$cmd_uname = '/usr/bin/uname';
+$cmd_uniq = '/usr/bin/uniq';
+
+chomp($uname_p = `$cmd_uname -p`);
+
+
+# Initialize constants:
+
+$solaris_library_ld_path = "/usr/openwin/lib:/usr/dt/lib";
+
+# Prefix for every object's profiling (etc) subdir in $working_dir.
+$object_dir = 'objects/';
+
+$text{'Summary_Result_None_Checked'} = gettext(
+ "No binaries were checked.");
+$text{'Summary_Result_Some_Failed'} = gettext(
+ "Potential binary stability problem(s) detected.");
+$text{'Summary_Result_Some_Incomplete'} = gettext(
+ "No stability problems detected, but not all binaries were checked.");
+$text{'Summary_Result_All_Passed'} = gettext(
+ "No binary stability problems detected.");
+
+
+$text{'Message_Private_Symbols_Check_Outfile'} = <<"END";
+#
+# <binary>|<abi>|<caller>|<callee>|private|<symbol>
+#
+END
+
+$text{'Message_Public_Symbols_Check_Outfile'} =
+ $text{'Message_Private_Symbols_Check_Outfile'};
+$text{'Message_Public_Symbols_Check_Outfile'} =~ s/private/public/g;
+
+#
+# Maps a filesystem path of a binary object to a subdirectory name (in
+# $working_dir). $working_dir is NOT prepended.
+#
+# Maps, e.g., /home/auser/bin/netscape.sparc
+# ===> objects/:=home=auser=bin=netscape.sparc
+#
+sub object_to_dir_name
+{
+ my ($filename) = @_;
+
+ my $dirname = $filename;
+
+ # protect any percents there:
+ $dirname =~ s,%,%%,g;
+
+ # protect any equals there:
+ $dirname =~ s,=,%=,g;
+
+ # now change slashes to equals:
+ $dirname =~ s,/,=,g;
+
+ #
+ # Prepend "objects/" and ":" tag to avoid dirname starting
+ # with "=" or "."
+ #
+ $dirname = $object_dir . ':' . $dirname;
+
+ return $dirname;
+}
+
+#
+# Takes the application output data directory and returns the path to
+# the actual binary.
+#
+sub dir_name_to_path
+{
+ my ($dirname) = @_;
+ my $path = '';
+
+ if (! -f "$dirname/info.path") {
+ exiter(nofile("$dirname/info.path", $!));
+ } else {
+ my $info_path_fh = do { local *FH; *FH };
+ open($info_path_fh, "<$dirname/info.path") ||
+ exiter(nofile("$dirname/info.path", $!));
+ chomp($path = <$info_path_fh>);
+ close($info_path_fh);
+ }
+
+ return $path;
+}
+
+#
+# This subroutine repeatly returns the object dirnames in the
+# working_dir. The full path to the dirname is returned. "undef" is
+# returned when all have been cycled through.
+#
+sub next_dir_name
+{
+ # object directory:
+ my $object_directory = $working_dir;
+ $object_directory .= "/" . $object_dir if ($object_dir);
+
+ # Check if we have the directory handle already open:
+ if (! defined($next_dir_name_dh)) {
+ # If not, then opendir it:
+ $next_dir_name_dh = do { local *FH; *FH };
+ if (! opendir($next_dir_name_dh, $object_directory)) {
+ exiter(nodir($object_directory, $!));
+ }
+ }
+
+ my $dirname;
+
+ #
+ # Loop over directory entries until one matches the magic tag
+ # "object:" Return undef when done reading the directory.
+ #
+ while (1) {
+ $dirname = readdir($next_dir_name_dh);
+
+ if (! defined($dirname)) {
+ # Done with dir. Clean up for next time:
+ closedir($next_dir_name_dh);
+ undef($next_dir_name_dh);
+ return undef;
+ } elsif ($dirname =~ m,^:,) {
+ # Return the full path to object's directory:
+ return "$object_directory/$dirname";
+ }
+ }
+}
+
+#
+# When appcert started up, it stored the /usr/bin/file output in the
+# app's output directory (appcert: record_binary()). This subroutine
+# retrieves it. If it cannot find it, it runs the file command
+# instead. The result is stored in memory in %cmd_output_file_cache
+#
+# Returns the single line of "file" output including the "\n". It
+# returns the null string if it had trouble, usually only if filename
+# doesn't exist.
+#
+sub cmd_output_file
+{
+ my ($filename) = @_;
+
+ # Check if we have it cached:
+ if (exists($cmd_output_file_cache{$filename})) {
+ return $cmd_output_file_cache{$filename};
+ }
+
+ # Otherwise, try to look it up in the $working_dir:
+ my $outfile = object_to_dir_name($filename);
+ $outfile = "$working_dir/$outfile/info.file";
+
+ my $str;
+
+ if (-f $outfile) {
+ my $file_cmd_fh = do { local *FH; *FH };
+ if (open($file_cmd_fh, "<$outfile")) {
+ $str = <$file_cmd_fh>;
+ close($file_cmd_fh);
+ }
+ }
+
+ # Otherwise run /usr/bin/file on it:
+ if (! defined($str) && -f $filename && $filename !~ /'/) {
+ c_locale(1);
+ $str = `$cmd_file '$filename' 2>/dev/null`;
+ c_locale(0);
+ }
+
+ $cmd_output_file_cache{$filename} = $str;
+
+ return $str;
+}
+
+#
+# When appcert started up, it stored the /usr/ccs/bin/dump output in the
+# app's output directory (appcert: record_binary()). This subroutine
+# retrieves it. If it cannot find it, it runs the dump -Lv command
+# instead. The result is stored in memory in %cmd_output_dump_cache
+#
+# Returns the "dump -Lv" output. It returns the null string if it had
+# trouble, usually only if filename doesn't exist.
+#
+sub cmd_output_dump
+{
+ my ($filename) = @_;
+
+ # Check if we have it cached:
+ if (exists($cmd_output_dump_cache{$filename})) {
+ return $cmd_output_dump_cache{$filename};
+ }
+
+ # Otherwise, try to look it up in the $working_dir:
+ my $outfile = object_to_dir_name($filename);
+ $outfile = "$working_dir/$outfile/info.dump";
+
+ my $str;
+
+ if (-f $outfile) {
+ my $dump_cmd_fh = do { local *FH; *FH };
+ if (open($dump_cmd_fh, "<$outfile")) {
+ while (<$dump_cmd_fh>) {
+ $str .= $_;
+ }
+ close($dump_cmd_fh);
+ }
+ }
+
+ # Otherwise run /usr/ccs/bin/dump -Lv on it:
+ if (! defined($str) && -f $filename && $filename !~ /'/) {
+ c_locale(1);
+ $str = `$cmd_dump -Lv '$filename' 2>/dev/null`;
+ c_locale(0);
+ }
+
+ $cmd_output_dump_cache{$filename} = $str;
+
+ return $str;
+}
+
+#
+# When symprof runs it stores the /usr/bin/ldd output in the app's
+# output directory (symprof: dynamic_profile()). This subroutine
+# retrieves it. If it cannot find it, it runs the ldd command instead.
+# The result is stored in memory in %all_ldd_neededs_cache
+#
+# Returns a "neededs hash" as output. The keys being the things needed
+# (left side of " => ") and the values are the resolution (right side of
+# " => "). It returns the null hash if it had trouble, usually only if
+# filename doesn't even exist, or if the object is not dynamically
+# linked.
+#
+sub all_ldd_neededs
+{
+ my ($filename) = @_;
+
+ my (%all_neededs);
+
+ my $output;
+
+ # Check if we have it cached:
+ if (exists($all_ldd_neededs_cache{$filename})) {
+ $output = $all_ldd_neededs_cache{$filename};
+ }
+
+ if (! defined($output)) {
+ # Otherwise, try to look it up in the $working_dir:
+ my $outfile = object_to_dir_name($filename);
+ $outfile = "$working_dir/$outfile/profile.dynamic.ldd";
+
+ if (-f $outfile) {
+ my $all_neededs_fh = do { local *FH; *FH };
+ if (open($all_neededs_fh, "<$outfile")) {
+ while (<$all_neededs_fh>) {
+ next if (/^\s*#/);
+ $output .= $_;
+ }
+ }
+ close($all_neededs_fh);
+ }
+ }
+
+ my ($str, $line, $l1, $l2);
+ if (! defined($output) && -f $filename && $filename !~ /'/) {
+ # Otherwise run /usr/bin/ldd on it:
+ c_locale(1);
+ $str = `$cmd_ldd '$filename' 2>/dev/null`;
+ c_locale(0);
+ foreach $line (split(/\n/, $str)) {
+ $line = trim($line);
+ $output .= "$line\n";
+ }
+ }
+
+ if (! defined($output)) {
+ #
+ # Set the output to the null string so following loop
+ # will do nothing and thus the empty hash will be
+ # returned.
+ #
+ $output = '';
+ }
+
+ $all_ldd_neededs_cache{$filename} = $output;
+
+ foreach $line (split(/\n/, $output)) {
+ ($l1, $l2) = split(/\s*=>\s*/, $line);
+ $l1 = trim($l1);
+ $l2 = trim($l2);
+ $all_neededs{$l1} = $l2;
+ if ($l2 !~ /file not found/) {
+ $all_neededs{$l2} = $l2;
+ }
+ }
+
+ return %all_neededs;
+}
+
+#
+# Create a string with all of the needed objects (direct and indirect).
+# This is intended for object name matching. See the 'needed' MATCH
+# entries in etc.warn.
+#
+sub all_ldd_neededs_string
+{
+ my ($filename) = @_;
+ my (%hash, $key);
+ my $str = '';
+ %hash = all_ldd_neededs($filename);
+ foreach $key (keys(%hash)) {
+ $str .= "$key $hash{$key}\n";
+ }
+ return $str;
+}
+
+#
+# Create a list with all of the directly bound symbols. This is
+# intended for symbol call matching. See the 'syms' MATCH entries in
+# etc.warn.
+#
+sub direct_syms
+{
+ my ($filename) = @_;
+ #
+ # We stored the dynamic profile output in the app's output
+ # directory. This subroutine retrieves it, identifies the
+ # direct bindings symbol names and places them in a newline
+ # separated string returned to caller.
+ #
+ my $direct_syms = '';
+
+ my $outfile = object_to_dir_name($filename);
+ $outfile = "$working_dir/$outfile/profile.dynamic";
+
+ my $prof_fh = do { local *FH; *FH };
+ if (! open($prof_fh, "<$outfile")) {
+ exiter(nofile($outfile, $!));
+ }
+ my ($app, $caller, $lib, $sym);
+ while (<$prof_fh>) {
+ next if (/^\s*#/);
+ next if (/^\s*$/);
+ chop;
+ ($app, $caller, $lib, $sym) = split(/\|/, $_, 4);
+ next unless ($caller eq '*DIRECT*');
+ $direct_syms .= "$sym\n";
+ }
+ close($prof_fh);
+
+ return $direct_syms;
+}
+
+#
+# Block to keep export_list private
+#
+{
+ my %export_list = (
+ 'AC_LIB_DIR', 'appcert_lib_dir',
+ 'AC_WORKING_DIR', 'working_dir',
+ 'AC_TMP_DIR', 'tmp_dir',
+ 'AC_BINARY_COUNT', 'binary_count',
+ 'AC_BLOCK_MIN', 'block_min',
+ 'AC_BLOCK_MAX', 'block_max',
+ 'AC_BATCH_REPORT', 'batch_report',
+ );
+
+
+ #
+ # Subroutine to read in possibly exported variables
+ #
+ sub import_vars_from_environment
+ {
+ no strict qw(refs);
+
+ while (my ($evar, $pvar) = each(%export_list)) {
+ $pvar = $export_list{$evar};
+ if (exists($ENV{$evar})) {
+ $$pvar = $ENV{$evar};
+ } else {
+ $$pvar = '';
+ }
+ }
+ }
+
+ #
+ # Exports the variables in %export_list to the environment.
+ #
+ sub export_vars_to_environment
+ {
+ my $pval;
+ no strict qw(refs);
+
+ while (my ($evar, $pvar) = each(%export_list)) {
+ $pvar = $export_list{$evar};
+ $pval = $$pvar;
+ if (defined($pval)) {
+ $ENV{$evar} = $pval;
+ }
+ }
+ }
+}
+
+#
+# Routine for turning on or off LC_ALL environment variable 'C'. When
+# we want command output that we will parse we set LC_ALL=C. On the
+# other hand, when we want to pass command output to the user we retain
+# their locale (if any).
+#
+sub c_locale
+{
+ my ($action) = @_;
+
+ #
+ # example usage:
+ # c_locale(1);
+ # $output = `some_cmd some_args 2>/dev/null`;
+ # c_locale(0);
+ #
+
+ if ($action) {
+ if (defined($ENV{'LC_ALL'})) {
+ $LC_ALL = $ENV{'LC_ALL'};
+ } else {
+ $LC_ALL = '__UNSET__';
+ }
+ $ENV{'LC_ALL'} = 'C';
+ } else {
+ if ($LC_ALL eq '__UNSET__') {
+ delete $ENV{'LC_ALL'};
+ } else {
+ $ENV{'LC_ALL'} = $LC_ALL;
+ }
+ }
+}
+
+#
+# Set or get the overall appcert result/return code.
+#
+sub overall_result_code
+{
+ my ($val) = @_;
+ #
+ # The code has significance (see below) and is the numerical
+ # exit() code for the appcert script.
+ #
+ # Code can be number followed by 1-line description.
+ #
+ # 0 appcert completed OK and ZERO binaries had problems detected
+ # and ZERO binaries had "warnings".
+ # 1 appcert failed somehow
+ # 2 appcert completed OK and SOME binaries had problems detected.
+ # 3 appcert completed OK and ZERO binaries had problems detected.
+ # and SOME binaries had "warnings".
+ #
+ # When called with a no arguments, only the number is returned.
+ # When called with a non-null argument it is written to the rc file.
+ #
+
+ my ($return_code_file, $line);
+
+ $return_code_file = "$working_dir/ResultCode";
+
+ my $rc_file_fh = do { local *FH; *FH };
+ if (! defined($val)) {
+ if (! -f $return_code_file) {
+ emsg("%s", nofile($return_code_file));
+ return 1;
+ }
+ open($rc_file_fh, "<$return_code_file") ||
+ exiter(nofile($return_code_file, $!));
+ chomp($line = <$rc_file_fh>);
+ close($rc_file_fh);
+ if ($line =~ /^(\d+)/) {
+ return $1;
+ } else {
+ return $line;
+ }
+ } else {
+ $val = trim($val);
+ if ($val !~ /^\d+/) {
+ $val = "1 $val";
+ }
+ open($rc_file_fh, ">$return_code_file") ||
+ exiter(nofile($return_code_file, $!));
+ print $rc_file_fh $val, "\n";
+ close($rc_file_fh);
+ return;
+ }
+}
+
+#
+# Sorter for strings like: "something 14", sorts on count (number)
+# first, then by string.
+#
+sub sort_on_count
+{
+ my $soc_cmp = sub {
+ my($n1, $n2);
+ if ($a =~ /(\d+)\s*$/) {
+ $n1 = $1;
+ } else {
+ $n1 = 0;
+ }
+ if ($b =~ /(\d+)\s*$/) {
+ $n2 = $1;
+ } else {
+ $n2 = 0;
+ }
+
+ if ($n1 == $n2) {
+ # if the numbers are "tied", then compare the
+ # string portion.
+ $a cmp $b;
+ } else {
+ # otherwise compare numerically:
+ $n2 <=> $n1;
+ }
+ };
+ return sort $soc_cmp @_;
+}
+
+#
+# Trims leading and trailing whitespace from a string.
+#
+sub trim
+{
+ my ($x) = @_;
+ if (! defined($x)) {
+ return '';
+ }
+ $x =~ s/^\s*//;
+ $x =~ s/\s*$//;
+ return $x;
+}
+
+#
+# Prints a line to filehandle or STDOUT.
+#
+sub print_line
+{
+ my ($fh) = @_;
+ if (defined($fh)) {
+ print $fh '-' x 72, "\n";
+ } else {
+ print STDOUT '-' x 72, "\n";
+ }
+}
+
+#
+# Returns formatted output of list items that fit in 80 columns, e.g.
+# Gelf_got_title 1 Gelf_reloc_entry 1
+# Gelf_ver_def_print 1 Gelf_syminfo_entry_title 1
+# Gelf_sym_table_title 1 Gelf_elf_header 1
+#
+sub list_format
+{
+ my ($indent, @list) = @_;
+
+ # $indent is a string which shifts everything over to the right.
+
+ my $width = 0;
+ my ($item, $len, $space);
+
+ foreach $item (@list) { # find the widest list item.
+ $len = length($item);
+ $width = $len if ($len > $width);
+ }
+ $width += 2; # pad 2 spaces for each column.
+
+ if ($width > (80 - length($indent))) {
+ $width = 80 - length($indent);
+ }
+
+ # compute number of columns:
+ my $columns = int((80 - length($indent))/$width);
+
+ # initialize:
+ my $current_column = 0;
+ my $text = $indent;
+
+ # put the items into lined up columns:
+ foreach $item (@list) {
+ if ($current_column >= $columns) {
+ $text .= "\n";
+ $current_column = 0;
+ $text .= $indent;
+ }
+ $space = $width - length($item);
+ $text .= $item . ' ' x $space if ($space > 0);
+ $current_column++;
+ }
+ $text .= "\n" if ($current_column);
+
+ return $text;
+}
+
+#
+# Wrapper for STDERR messages.
+#
+sub emsg
+{
+ printf STDERR @_;
+}
+
+#
+# Wrapper for STDOUT messages.
+#
+sub pmsg
+{
+ printf STDOUT @_;
+}
+
+#
+# Error message for a failed file open.
+#
+sub nofile
+{
+ my $msg = "$command_name: ";
+ $msg .= gettext("cannot open file: %s\n");
+ $msg = sprintf($msg, join(' ', @_));
+
+ return $msg;
+}
+
+#
+# Error message for an invalid file path.
+#
+sub nopathexist
+{
+ my $msg = "$command_name: ";
+ $msg .= gettext("path does not exist: %s\n");
+ $msg = sprintf($msg, join(' ', @_));
+
+ return $msg;
+}
+
+#
+# Error message for a failed running of a command.
+#
+sub norunprog
+{
+ my $msg = "$command_name: ";
+ $msg .= gettext("cannot run program: %s\n");
+ $msg = sprintf($msg, join(' ', @_));
+
+ return $msg;
+}
+
+#
+# Error message for a failed directory creation.
+#
+sub nocreatedir
+{
+ my $msg = "$command_name: ";
+ $msg .= gettext("cannot create directory: %s\n");
+ $msg = sprintf($msg, join(' ', @_));
+
+ return $msg;
+}
+
+#
+# Error message for a failed directory opendir.
+#
+sub nodir
+{
+ my $msg = "$command_name: ";
+ $msg .= gettext("cannot open directory: %s\n");
+ $msg = sprintf($msg, join(' ', @_));
+
+ return $msg;
+}
+
+#
+# exiter routine wrapper is used primarily to abort. Calls
+# clean_up_exit() routine if that routine is defined. Prints $msg to
+# STDERR and exits with exit code $status $status is 1 (aborted command)
+# by default.
+#
+sub exiter
+{
+ my ($msg, $status) = @_;
+
+ if (defined($msg) && ! defined($status) && $msg =~ /^\d+$/) {
+ $status = $msg;
+ undef($msg);
+ }
+ if (! defined($status)) {
+ $status = 1;
+ }
+
+ if (defined($msg)) {
+ #
+ # append a newline unless one is already there or string
+ # is empty:
+ #
+ $msg .= "\n" unless ($msg eq '' || $msg =~ /\n$/);
+ emsg($msg);
+ }
+ if (defined($clean_up_exit_routine)) {
+ &$clean_up_exit_routine($status);
+ }
+
+ exit $status;
+}
+
+sub set_clean_up_exit_routine
+{
+ my($code_ref) = @_;
+ $clean_up_exit_routine = $code_ref;
+}
+
+#
+# Generic routine for setting up signal handling. (usually just a clean
+# up and exit routine).
+#
+# Call with mode 'on' and the name of the handler subroutine.
+# Call with mode 'off' to set signal handling back to defaults
+# (e.g. a handler wants to call signals('off')).
+# Call it with 'ignore' to set them to ignore.
+#
+sub signals
+{
+ my ($mode, $handler) = @_;
+
+ # List of general signals to handle:
+ my (@sigs) = qw(INT QUIT);
+
+ my $sig;
+
+ # Loop through signals and set the %SIG array accordingly.
+
+ if ($mode eq 'on') {
+ foreach $sig (@sigs) {
+ $SIG{$sig} = $handler;
+ }
+ } elsif ($mode eq 'off') {
+ foreach $sig (@sigs) {
+ $SIG{$sig} = 'DEFAULT';
+ }
+ } elsif ($mode eq 'ignore') {
+ foreach $sig (@sigs) {
+ $SIG{$sig} = 'IGNORE';
+ }
+ }
+}
+
+#
+# Creates a temporary directory with a unique name. Directory is
+# created and the directory name is return. On failure to create it,
+# null string is returned.
+#
+sub create_tmp_dir
+{
+ my ($basedir) = @_;
+ #
+ # If passed a prefix in $prefix, try to create a unique tmp dir
+ # with that basedir. Otherwise, it will make a name in /tmp.
+ #
+ # If passed a directory that already exists, a subdir is created
+ # with madeup basename "prefix.suffix"
+ #
+
+ my $cmd = $command_name;
+ $cmd = 'tempdir' unless (defined($cmd) && $cmd ne '');
+
+ if (! defined($basedir) || ! -d $basedir) {
+ $basedir = "/tmp/$cmd";
+ } else {
+ $basedir = "$basedir/$cmd";
+ }
+
+ my $suffix = $$;
+ if ($tmp_dir_count) {
+ $suffix .= ".$tmp_dir_count";
+ }
+ my $dir = "$basedir.$suffix";
+ $tmp_dir_count++;
+ if ($dir =~ m,^/tmp/,) {
+ if (! mkpath($dir, 0, 0700) || ! -d $dir) {
+ emsg("%s", nocreatedir($dir, $!));
+ return '';
+ }
+ } else {
+ if (! mkpath($dir) || ! -d $dir) {
+ emsg("%s", nocreatedir($dir, $!));
+ return '';
+ }
+ }
+ return $dir;
+}
+
+#
+# Checks to see if a directory is empty. Returns 1 if the directory is.
+# returns 0 if it is not or if directory does not exist.
+#
+sub dir_is_empty
+{
+ my ($dir) = @_;
+
+ return 0 if (! -d $dir);
+
+ my $is_empty = 1;
+
+ my $dir_is_empty_dh = do { local *FH; *FH };
+ if (opendir($dir_is_empty_dh, $dir)) {
+ my $subdir;
+ foreach $subdir (readdir($dir_is_empty_dh)) {
+ if ($subdir ne '.' && $subdir ne '..') {
+ $is_empty = 0;
+ last;
+ }
+ }
+ close($dir_is_empty_dh);
+ } else {
+ return 0;
+ }
+
+ return $is_empty;
+}
+
+#
+# Follows a symbolic link until it points to a non-symbolic link. If
+# $file is not a symlink but rather a file, returns $file. Returns null
+# if what is pointed to does not exist.
+#
+sub follow_symlink
+{
+ my ($file) = @_;
+
+ if (! -e $file) {
+ # We will never find anything:
+ return '';
+ }
+
+ if (! -l $file) {
+ # Not a symlink:
+ return $file;
+ }
+
+ my ($tmp1, $tmp2);
+
+ $tmp1 = $file;
+
+ while ($tmp2 = readlink($tmp1)) {
+
+ if ($tmp2 !~ m,^/,) {
+ $tmp2 = dirname($tmp1) . "/" . $tmp2;
+ }
+
+ $tmp1 = $tmp2; #
+ $tmp1 =~ s,/+,/,g; # get rid of ////
+ $tmp1 =~ s,^\./,,g; # remove leading ./
+ $tmp1 =~ s,/\./,/,g; # remove /./
+ $tmp1 =~ s,/+,/,g; # get rid of //// again
+ $tmp1 =~ s,/[^/]+/\.\./,/,g; # remove "abc/.."
+ #
+
+ if (! -e $tmp1) {
+ $tmp1 = $tmp2;
+ }
+ if (! -e $tmp1) {
+ return '';
+ }
+ }
+
+ return $tmp1;
+}
+
+#
+# Examines if the file is statically linked. Can be called on any file,
+# but it is preferable to run it on things known to be executables or
+# libraries.
+#
+# Returns 0 if not statically linked. Otherwise, returns 1.
+#
+sub is_statically_linked
+{
+ my ($file) = @_;
+
+ my $tmp;
+ my $file_cmd_output;
+ $file_cmd_output = cmd_output_file($file);
+
+ if ($file_cmd_output eq '') {
+ return 1;
+ }
+
+ if ($file_cmd_output =~ /[:\s](.*)$/) {
+ $tmp = $1;
+ if ($tmp =~ /ELF.*statically linked/) {
+ return 1;
+ } elsif ($tmp =~ /Sun demand paged/) {
+ if ($tmp !~ /dynamically linked/) {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+#
+# Examines first 4 bytes of file. Returns 1 if they are "\x7fELF".
+# Otherwise, returns 0.
+#
+sub is_elf
+{
+ my ($file) = @_;
+
+ my ($buf, $n);
+ my $cmp = "\x7fELF";
+ if (! -r $file) {
+ return 0;
+ }
+
+ my $is_elf_fh = do { local *FH; *FH };
+ if (open($is_elf_fh, "<$file")) {
+ $n = read($is_elf_fh, $buf, 4);
+ close($is_elf_fh);
+ if ($n != 4) {
+ return 0;
+ }
+ if ($buf eq $cmp) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#
+# Returns 1 if $file is a shared object (i.e. ELF shared library)
+# Returns 0 if it is not.
+#
+# Routine uses the dump -Lv output to determine this. Failing that, it
+# examines the /usr/bin/file output.
+#
+sub is_shared_object
+{
+ my ($file) = @_;
+
+ return 0 unless (-f $file);
+
+ my ($on, $line, $is_shared_object);
+ my ($n, $tag, $val);
+
+ $on = 0;
+ $is_shared_object = 0;
+
+ foreach $line (split(/\n/, cmd_output_dump($file))) {
+
+ if ($line =~ /^\[INDEX\]/) {
+ $on = 1;
+ next;
+ }
+ next unless ($on);
+ ($n, $tag, $val) = split(/\s+/, trim($line));
+ if ($tag eq "SONAME") {
+ $is_shared_object = 1;
+ last;
+ }
+ }
+
+ if (! $is_shared_object) {
+ # If it is ELF, file output will say "dynamic lib":
+ $line = cmd_output_file($file);
+ if ($line =~ /ELF.* dynamic lib /) {
+ $is_shared_object = 1;
+ }
+ }
+
+ return $is_shared_object;
+}
+
+#
+# Used for the a.out warning in etc.warn. Examines first 4 bytes of
+# file, and returns 1 if SunOS 4.x a.out binary 0 otherwise.
+#
+sub is_aout
+{
+ my ($file) = @_;
+
+ my ($buf, $n);
+ my $cmp1 = "\001\013";
+ my $cmp2 = "\001\010";
+ my $cmp3 = "\001\007";
+ if (! -r $file) {
+ return 0;
+ }
+
+ my $is_aout_fh = do { local *FH; *FH };
+ if (open($is_aout_fh, "<$file")) {
+ $n = read($is_aout_fh, $buf, 4);
+ close($is_aout_fh);
+ if ($n != 4) {
+ return 0;
+ }
+ $buf = substr($buf, 2);
+ if ($buf eq $cmp1) {
+ return 1;
+ }
+ if ($buf eq $cmp2) {
+ return 1;
+ }
+ if ($buf eq $cmp3) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#
+# is_suid
+# Returns 1 if $file is a set user ID file.
+# Returns 2 if $file otherwise is a set group ID (but not suid).
+# Returns 0 if it is neither or file does not exist.
+#
+sub is_suid
+{
+ my ($file) = @_;
+
+ return 0 unless (-f $file);
+
+ my ($mask, $mode, $test);
+ my @is_suid_masks = (04000, 02010, 02030, 02050, 02070);
+
+ $mode = (stat($file))[2];
+
+ foreach $mask (@is_suid_masks) {
+ $test = $mode & $mask;
+ if ($test == $mask) {
+ if ($mask == $is_suid_masks[0]) {
+ return 1;
+ } else {
+ return 2;
+ }
+ }
+ }
+ return 0;
+}
+
+#
+# Returns a list of (abi, [ELF|a.out], wordsize, endianness)
+#
+sub bin_type
+{
+ my ($filename) = @_;
+
+ my ($abi, $e_machine, $type, $wordsize, $endian, $rest);
+
+ $abi = 'unknown';
+ $e_machine = 'unknown';
+ $type = 'unknown';
+ $wordsize = 'unknown';
+ $endian = 'unknown';
+
+ # Try to look it up in the $working_dir:
+ my $outfile = object_to_dir_name($filename);
+ $outfile = "$working_dir/$outfile/info.arch";
+
+ if (-f $outfile) {
+ my $arch_info_fh = do { local *FH; *FH };
+ if (open($arch_info_fh, "<$outfile")) {
+ while (<$arch_info_fh>) {
+ chomp;
+ if (/^ARCH:\s*(\S.*)$/) {
+ $abi = $1;
+ } elsif (/^TYPE:\s*(\S.*)$/) {
+ $type = $1;
+ } elsif (/^WORDSIZE:\s*(\S.*)$/) {
+ $wordsize = $1;
+ } elsif (/^BYTEORDER:\s*(\S.*)$/) {
+ $endian = $1;
+ }
+ }
+ close($arch_info_fh);
+ }
+ return ($abi, $type, $wordsize, $endian);
+ }
+
+ # Otherwise, process /usr/bin/file output:
+ my $file_output;
+ $file_output = cmd_output_file($filename);
+
+ if ($file_output =~ /Sun demand paged SPARC|pure SPARC/) {
+ $type = 'a.out';
+ $abi = 'sparc';
+ $e_machine = 'SPARC';
+ $wordsize = '32';
+ $endian = 'MSB';
+ } elsif ($file_output =~ /ELF\s+/) {
+ $type = 'ELF';
+ $rest = $';
+ if ($rest =~ /^(\d+)-bit\s+/) {
+ $wordsize = $1;
+ $rest = $';
+ }
+ if ($rest =~ /^(LSB|MSB)\s+/) {
+ $endian = $1;
+ $rest = $';
+ }
+ if ($rest =~ /SPARC/) {
+ if ($rest =~ /\bSPARC\b/) {
+ $abi = 'sparc';
+ $e_machine = 'SPARC';
+ } elsif ($rest =~ /\bSPARC32PLUS\b/) {
+ $abi = 'sparc';
+ $e_machine = 'SPARC32PLUS';
+ } elsif ($rest =~ /\bSPARCV9\b/) {
+ $abi = 'sparcv9';
+ $e_machine = 'SPARCV9';
+ }
+ } else {
+ if ($rest =~ /\bAMD64\b/ ||
+ $wordsize == 64 && $endian eq 'LSB') {
+ $abi = 'amd64';
+ $e_machine = 'AMD64';
+ } elsif ($rest =~ /\b80386\b/) {
+ $abi = 'i386';
+ $e_machine = '80386';
+ }
+ }
+ }
+ return ($abi, $type, $wordsize, $endian, $e_machine);
+}
+
+#
+# Compares two files to see if they are the same. First tries some
+# string comparisons. Then, if $fast is not true, attempts an inode
+# comparison.
+#
+sub files_equal
+{
+ my ($file1, $file2, $fast) = @_;
+
+ my ($f1, $f2);
+
+ #
+ # If they are the same string, we say they are equal without
+ # checking if they do exist.
+ #
+
+ if ($file1 eq $file2) {
+ return 1;
+ }
+
+ # Try trimming off any leading "./"
+ $f1 = $file1;
+ $f2 = $file2;
+
+ $f1 =~ s,^\./+,,;
+ $f2 =~ s,^\./+,,;
+
+ if ($f1 eq $f2) {
+ return 1;
+ }
+
+ # That is all we do if doing a fast compare.
+ return 0 if ($fast);
+
+ # Otherwise, resort to the file system:
+
+ my ($inode1, $inode2);
+ $inode1 = file_inode($file1);
+ $inode2 = file_inode($file2);
+
+ if (! defined($inode1) || ! defined($inode2) ||
+ $inode1 < 0 || $inode2 < 0) {
+ return 0;
+ } elsif ($inode1 eq $inode2) {
+ return 1;
+ }
+ return 0;
+}
+
+#
+# Utility to return the inode of a file. Used to determine if two
+# different paths or a path + symlink point to the same actual file.
+#
+sub file_inode
+{
+ my ($file) = @_;
+
+ my $inode;
+ if (exists($file_inode_cache{$file})) {
+ return $file_inode_cache{$file};
+ }
+
+ if (! file_exists($file)) {
+ $file_inode_cache{$file} = -1;
+ return -1;
+ }
+
+ $inode = (stat($file))[1];
+
+ if (! defined($inode) || $inode !~ /^\d+$/) {
+ $inode = -1;
+ }
+
+ $file_inode_cache{$file} = $inode;
+ return $inode;
+}
+
+#
+# Existence test for files. Caches the results for speed.
+#
+sub file_exists
+{
+ my ($file) = @_;
+
+ if (exists($file_exists_cache{$file})) {
+ return $file_exists_cache{$file};
+ }
+
+ my $x;
+ if (-e $file) {
+ $x = 1;
+ } else {
+ $x = 0;
+ }
+ $file_exists_cache{$file} = $x;
+
+ return $x;
+}
+
+#
+# This routine deletes the caches we store information (e.g. cmd output)
+# in to improve performance. It is called when the caches are suspected
+# to be too large.
+#
+sub purge_caches
+{
+ undef %file_exists_cache;
+ undef %file_inode_cache;
+ undef %filter_lib_cache;
+ undef %cmd_output_file_cache;
+ undef %cmd_output_dump_cache;
+ undef %all_ldd_neededs_cache;
+}
+
+#
+# Given a filter library, this routine tries to determine if it is a
+# STANDARD filter or an AUXILIARY filter. This is done by running dump
+# -Lv on the filter library. Results are cached in the global
+# filter_lib_cache to avoid calling dump many times on the same library
+# (e.g. libc.so.1).
+#
+sub filter_lib_type
+{
+ my ($filter) = @_;
+
+ my $type = 'unknown';
+
+ if (exists($filter_lib_cache{$filter})) {
+ return $filter_lib_cache{$filter};
+ }
+
+ if (! -f $filter) {
+ $filter_lib_cache{$filter} = 'unknown';
+ return 'unknown';
+ }
+
+ my $dump_output;
+ $dump_output = cmd_output_dump($filter);
+
+ if (! $dump_output) {
+ emsg(gettext("could not determine library filter type: %s\n"),
+ $filter);
+ $filter_lib_cache{$filter} = 'unknown';
+
+ } else {
+ my ($line, $dump, $idx, $tag, $val);
+ my ($saw_filter, $saw_aux);
+ $saw_filter = 0;
+ $saw_aux = 0;
+ foreach $line (split(/\n/, $dump_output)) {
+ next unless ($line =~ /^\[\d+\]/);
+ $dump = trim($line);
+ ($idx, $tag, $val) = split(/\s+/, $dump);
+ # detect both names used for each filter type:
+ if ($tag eq 'FILTER' || $tag eq 'SUNW_FILTER') {
+ $type = 'STD';
+ $saw_filter = 1;
+ } elsif ($tag eq 'AUXILIARY' || $tag eq
+ 'SUNW_AUXILIARY') {
+ $type = 'AUX';
+ $saw_aux = 1;
+ }
+ }
+ if ($saw_filter && $saw_aux) {
+ $type = 'AUX';
+ }
+ $filter_lib_cache{$filter} = $type;
+ }
+ return $filter_lib_cache{$filter};
+}
+
+#
+# Calls "abi_index" to dynamically create the list of Solaris libraries
+# and their characteristics.
+#
+sub load_model_index
+{
+ my $dir = "auto"; # all model indexes are created automatically
+
+ if (exists($lib_index_loaded{$dir})) {
+ if ($lib_index_loaded{$dir} == -1) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+
+ my ($lib, $lib2, $def, $cnt, $link_cnt, $all_links);
+ my ($key, $base);
+
+ my $reading_cache_file;
+
+ $link_cnt = 0;
+ my $cache_file = "$working_dir/AbiIndex";
+ my $index_fh = do { local *FH; *FH };
+ my $cache_fh = do { local *FH; *FH };
+ if (-f $cache_file) {
+ open($index_fh, "<$cache_file") ||
+ exiter(nofile($cache_file, $!));
+ $reading_cache_file = 1;
+ } else {
+ if (! open($index_fh,
+ "$appcert_lib_dir/abi_index 2>/dev/null |")) {
+ exiter(noprogrun("abi_index", $!));
+ }
+ if (! open($cache_fh, ">$cache_file")) {
+ exiter(nofile($cache_file, $!));
+ }
+ $reading_cache_file = 0;
+ }
+
+ if (! $reading_cache_file) {
+ emsg("\n");
+ emsg(gettext("determining list of Solaris libraries"));
+ emsg(" ...\n");
+ }
+
+ my $abi;
+ while (<$index_fh>) {
+ next if (/^\s*#/);
+ next if (/^\s*$/);
+ print $cache_fh $_ if (! $reading_cache_file);
+ chomp;
+
+ ($abi, $lib, $def, $cnt, $all_links) = split(/\|/, $_, 5);
+
+ next if (! -f $lib);
+
+ $abi = 'any' if ($abi eq 'unknown');
+
+ # note if $all_links is empty, we still get the base lib.
+ foreach $lib2 ($lib, split(/:/, $all_links)) {
+ $key = "$dir|$lib2|$abi";
+ $lib_index_definition{$key} = $def;
+
+ $base = basename($lib2);
+ #
+ # store an index of lib basenames to be used for
+ # libfoo.so* matching.
+ #
+ $shared_object_index{$base}++;
+ $lib_index{$base}++ if ($base =~ /^lib/);
+
+ $link_cnt++;
+ }
+ #
+ # record the device/inode too, used to avoid confusion due
+ # to symlinks between *directories* instead of files. E.g.:
+ # /usr/lib/64 -> /usr/lib/sparcv9
+ # under some crle(1) configurations this can be
+ # particularly problematic.
+ #
+ if (-e $lib) {
+ my ($device, $inode) = (stat($lib))[0,1];
+ if (defined($device) && defined($inode)) {
+ $key = "$dir|$device/$inode|$abi";
+ $lib_index_definition{$key} = $def;
+ }
+ }
+ }
+ close($index_fh);
+ close($cache_fh) if (! $reading_cache_file);
+
+ # return 1 if library links were loaded. 0 indicates a failure.
+ push(@lib_index_loaded, $dir);
+ if ($link_cnt) {
+ $lib_index_loaded{$dir} = $link_cnt;
+ return 1;
+ } else {
+ $lib_index_loaded{$dir} = -1;
+ return 0;
+ }
+}
+
+#
+# Returns a list of Solaris library basenames matching a pattern. If a
+# directory name is in $pattern, it will be prepended to each item.
+#
+sub lib_match
+{
+ my ($pattern, $return_something) = @_;
+
+ if ($pattern eq '*') {
+ # special case '*'
+ return $pattern;
+ }
+
+ #
+ # $return_something = 1 means if there was nothing matched,
+ # return $pattern to the caller.
+ #
+ # This sub should only be called to initialize things since it
+ # is very slow. (runs the regex over all libraries) Do not call
+ # it in a loop over, say, application binaries. Rather, call it
+ # before the loop and make note of all the discrete cases.
+ #
+
+ # To handle libfoo.so* matching, we need the Index file loaded:
+ if (! $lib_match_initialized) {
+ load_model_index();
+ $lib_match_initialized = 1;
+ }
+
+ my (@list, @libs, $lib, $id, $patt0, $dir0);
+
+ # if empty, set it to "0" for the $id key.
+ $return_something = 0 if ($return_something eq '');
+ $id = "$pattern|$return_something";
+
+ if (defined($lib_match_cache{$id})) {
+ # If we have already found it, return the cached result.
+ return split(/\|/, $lib_match_cache{$id});
+ }
+
+ $patt0 = $pattern;
+ # extract dirname, if any.
+ if ($pattern =~ m,/,) {
+ $dir0 = dirname($pattern);
+ $pattern = basename($pattern);
+ } else {
+ $dir0 = '';
+ }
+
+ # turn the matching pattern into a regex:
+ $pattern =~ s/\./\\./g; # protect .'s
+ $pattern =~ s/\*/.*/g; # * -> .*
+ $pattern =~ s,/,\\/,g; # protect /'s (see below)
+
+ #
+ # create a little code to check the match, since there will be a
+ # big loop of checks: note the anchoring /^...$/
+ #
+ my $regex = qr/^$pattern$/;
+
+ if ($pattern =~ /^lib/) {
+ # for a bit of speed, the lib* set is much smaller, so use it:
+ @libs = keys(%lib_index);
+ } else {
+ # this is the full list:
+ @libs = keys(%shared_object_index);
+ }
+
+ # now try all libs for a match, and store in @list.
+ foreach $lib (@libs) {
+ if ($lib =~ /$regex/) {
+ if ($dir0 ne '') {
+ # put back the dirname:
+ $lib = "$dir0/$lib";
+ }
+ push(@list, $lib);
+ }
+ }
+
+ # return list and cache result:
+ if ($return_something && ! @list) {
+ $lib_match_cache{$id} = $patt0;
+ return $patt0;
+ } else {
+ $lib_match_cache{$id} = join('|', @list);
+ return @list;
+ }
+}
+
+#
+# Expand the matches in a etc.warn MATCH expression.
+# returns subroutine code for the comparison.
+#
+sub expand_expr
+{
+ my($expr) = @_;
+ my $code = 'my($fn) = @_; ';
+ $expr =~ s/\bfile\s*\=\~\s*/ cmd_output_file(\$fn) =~ /g;
+ $expr =~ s/\bdump\s*\=\~\s*/ cmd_output_dump(\$fn) =~ /g;
+ $expr =~ s/\bneeded\s*\=\~\s*/ all_ldd_neededs_string(\$fn) =~ /g;
+ $expr =~ s/\bsyms\s*\=\~\s*/ direct_syms(\$fn) =~ /g;
+
+ $code .= "if ($expr) {return 1;} else {return 0;}";
+ return $code;
+}
+
+#
+# Loads the binary stability information contained in the
+# /usr/lib/abi/appcert/etc.* files.
+#
+sub load_misc_check_databases
+{
+ my $etc_dir = "$appcert_lib_dir";
+
+ my ($etc_file, $line);
+
+ my (@etcs) = <$etc_dir/etc.*>;
+
+ #
+ # Event(etc.) types to handle:
+ #
+ # SCOPED_SYMBOL|<release>|<lib>|<sym>
+ # MODEL_TWEAK|<library>|<abi1,...>|<symbol>|<classification>
+ # REMOVED_SYMBOL|<release>|<lib>|<sym>
+ #
+
+ my ($tag, $rel, $lib, $sym, $rest);
+ my ($abis, $class, $tmp, $gather);
+
+ # Read in and process all the etc files:
+ my $count = 0;
+ foreach $etc_file (@etcs) {
+ my $etc_fh = do { local *FH; *FH };
+ if (! open($etc_fh, "<$etc_file")) {
+ exiter(nofile($etc_file, $!));
+ }
+ while (<$etc_fh>) {
+ # read each line:
+ chomp($line = $_);
+
+ # gather lines continued with "\" at end:
+ while ($line =~ /\\$/) {
+ chomp($line);
+ last if (eof($etc_fh));
+ chomp($tmp = <$etc_fh>);
+ # handle "-" ... "-" style text blocks.
+ if ($tmp eq '-') {
+ #
+ # gather everything until the
+ # next '-' line.
+ #
+ $gather = '';
+ while (1) {
+ last if (eof($etc_fh));
+ chomp($tmp = <$etc_fh>);
+ last if ($tmp eq '-');
+ $gather .= "|$tmp";
+ }
+ $line .= $gather;
+ } else {
+ $line .= " " . $tmp;
+ }
+ }
+
+ #
+ # skip blank lines or lines (including continued lines)
+ # beginning with "#"
+ #
+ next if ($line =~ /^\s*#/);
+ next if ($line =~ /^\s*$/);
+
+ my $lib2;
+
+ # Case statement for all the types:
+ if ($line =~ /^SCOPED_SYMBOL/) {
+ ($tag, $rel, $lib, $sym, $rest) =
+ split(/\|/, $line, 5);
+ #
+ # current implementation uses library basename.
+ #
+ # We may also want to split this value
+ # into a hash or two, e.g.
+ # Scope_Symbol_Release, etc..
+ #
+ # No lib_match wild-carding done for this case.
+ #
+ $scoped_symbol{"$lib|$sym"} .=
+ "$rel|$lib|$sym,";
+ $scoped_symbol_all{"$sym"} .=
+ "$rel|$lib|$sym,";
+ } elsif ($line =~ /^SKIP_SYMBOL/) {
+ #
+ # These are low-level, e.g. C runtime
+ # we always want to skip.
+ #
+ ($tag, $sym) = split(/\|/, $line, 2);
+ $skip_symbols{$sym} = 1;
+
+ } elsif ($line =~ /^MODEL_TWEAK/) {
+ #
+ # These are direct edits of symbol
+ # public/private database.
+ #
+ ($tag, $lib, $abis, $sym, $class) =
+ split(/\|/, $line, 5);
+ # change arch sep from "," to "%"
+ $abis =~ s/,/%/g;
+
+ my (@libs, $lib64, @tmp);
+ if ($lib =~ /\*/) {
+ @libs = lib_match($lib, 1);
+ } else {
+ push(@libs, $lib);
+ }
+ if ($abis eq '*') {
+ #
+ # '*' means all ABIs, so we modify
+ # pathnames to reflect the 64 bit
+ # versions. If these exists on the
+ # system, we append them to the list
+ # for this tweak.
+ #
+ @tmp = @libs;
+ foreach $lib2 (@tmp) {
+ if ($lib2 !~ m,/lib/,) {
+ next;
+ }
+ #
+ # check for existence of sparc
+ # and x86 64 bit versions.
+ #
+ $lib64 = $lib2;
+ $lib64 =~
+ s,/lib/,/lib/sparcv9/,;
+ if (-e $lib64) {
+ push(@libs, $lib64);
+ }
+ $lib64 = $lib2;
+ $lib64 =~ s,/lib/,/lib/amd64/,;
+ if (-e $lib64) {
+ push(@libs, $lib64);
+ }
+ $lib64 = $lib2;
+ $lib64 =~ s,/lib/,/lib/64/,;
+ if (-e $lib64) {
+ push(@libs, $lib64);
+ }
+ }
+ }
+
+ @tmp = @libs;
+ foreach $lib2 (@tmp) {
+ if ($lib2 !~ m,/, || ! -e $lib2) {
+ next;
+ }
+ #
+ # if it exists on the system,
+ # store info wrt inode as well:
+ #
+ my ($device, $inode);
+ ($device, $inode) = (stat($lib2))[0,1];
+ if ($device ne '' && $inode ne '') {
+ push(@libs, "$device/$inode");
+ }
+ }
+
+ #
+ # now store the tweak info for all associated
+ # libraries.
+ #
+ foreach $lib2 (@libs) {
+ $model_tweak{$lib2} .=
+ "$sym|$abis|$class,";
+ }
+
+ } elsif ($line =~ /^WARNING:/) {
+ #
+ # Extra warnings for miscellaneous problems.
+ #
+ my $cnt = 0;
+ my ($warn, $tag, $desc, $bindings);
+ my ($bind, $text);
+ ($warn, $tag, $desc, $bindings, $text) =
+ split(/:/, $line, 5);
+
+ # trim any leading spaces:
+ $tag =~ s/^\s*//;
+ $desc =~ s/^\s*//;
+ $bindings =~ s/^\s*//;
+ $text =~ s/^\s*//;
+
+ $tag =~ s,[\s/;]+,_,g;
+
+ #
+ # desc lists will be ";" delimited, so
+ # replace any found in the text.
+ #
+ $desc =~ s/;/,/g;
+ $desc = trim($desc);
+
+
+ # Store info in %Warnings_* hashes:
+
+ $warnings_desc{$tag} = $desc;
+
+ $warnings_match{$tag} = '';
+
+ if ($bindings =~ /^MATCH\s*(\S.*)$/) {
+ #
+ # Handle the pattern MATCH
+ # case. Note there there is no
+ # libfoo.so.* matching here.
+ #
+ my $expr = $1;
+ my $code;
+
+ #
+ # For efficiency we will create
+ # a subroutine for each case.
+ #
+
+ # get subref code:
+ $code = expand_expr($expr);
+
+ # define the subroutine:
+
+ my $subref;
+ eval "\$subref = sub { $code };";
+ if ("$@" eq "" && $subref) {
+ $warnings_match{$tag} = $subref;
+ }
+ } else {
+ #
+ # Otherwise, it is a
+ # lib|sym|caller type match
+ #
+ my ($lib, $sym, $rest);
+ foreach $bind (split(/,/, $bindings)) {
+ #
+ # Create pseudo tag,
+ # "tag|N", for each
+ # binding.
+ #
+ $bind = trim($bind);
+ ($lib, $sym, $rest) =
+ split(/\|/, $bind, 3);
+ foreach $lib2
+ (lib_match($lib, 1)) {
+ $tmp = "$tag|$cnt";
+ $warnings_bind{$tmp} =
+ "$lib2|$sym|$rest";
+ $warnings_desc{$tmp} =
+ $desc;
+ $cnt++;
+ }
+ }
+ }
+ }
+ }
+ $count++;
+ close($etc_fh);
+ }
+
+ # Trim any trailing "," separators from the last append:
+
+ my $key;
+ foreach $key (keys(%scoped_symbol)) {
+ $scoped_symbol{$key} =~ s/,+$//;
+ }
+ foreach $key (keys(%scoped_symbol_all)) {
+ $scoped_symbol_all{$key} =~ s/,+$//;
+ }
+ foreach $key (keys(%model_tweak)) {
+ $model_tweak{$key} =~ s/,+$//;
+ #
+ # make sure tweak is associated with device/inode to aid not
+ # getting tricked by symlinks under crle, LD_LIBRARY_PATH, etc.
+ #
+ my ($device, $inode) = (stat($key))[0,1];
+ if (defined($device) && defined($inode)) {
+ $model_tweak{"$device/$inode"} = $model_tweak{$key};
+ }
+ }
+ return $count;
+}
+
+1;
diff --git a/usr/src/cmd/abi/appcert/scripts/Makefile b/usr/src/cmd/abi/appcert/scripts/Makefile
new file mode 100644
index 0000000..9b08992
--- /dev/null
+++ b/usr/src/cmd/abi/appcert/scripts/Makefile
@@ -0,0 +1,106 @@
+#
+# 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) 1999-2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# cmd/abi/appcert/scripts/Makefile
+#
+
+SUFFIXES += .pl .pm
+
+PROG= appcert
+APPCERT_SUBCMDS= symcheck symprof symreport abi_index
+MODULES= AppcertUtil.pm
+
+SCRIPTS= $(PROG) $(APPCERT_SUBCMDS)
+MESSAGES= $(SCRIPTS:%=%.po) $(MODULES:%.pm=%.po)
+
+
+CLEANFILES= $(SCRIPTS) $(MESSAGES)
+CLOBBERFILES= $(SCRIPTS) $(MESSAGES)
+
+include $(SRC)/cmd/Makefile.cmd
+
+ROOTLIBABIDIR = $(ROOTLIB)/abi/appcert
+ROOTLIBABIFILES = $(APPCERT_SUBCMDS:%=$(ROOTLIBABIDIR)/%) \
+ $(MODULES:%=$(ROOTLIBABIDIR)/%)
+
+.KEEP_STATE:
+
+all: $(SCRIPTS) $(MODULES)
+
+#
+# install targets
+# Note: Makefile.cmd has a rule to cover $(ROOTSHFILES), but
+# $(ROOTLIBABIFILES) are special install targets (go into
+# dirs not covered by Makefile.cmd), so we provide an explicit
+# rule for that.
+#
+
+install: all .WAIT $(ROOTPROG) $(ROOTLIBABIDIR) .WAIT $(ROOTLIBABIFILES)
+
+_msg: $(MSGDOMAIN) $(MESSAGES)
+ $(CP) $(MESSAGES) $(MSGDOMAIN)
+
+$(MSGDOMAIN):
+ $(INS.dir)
+
+.pl:
+ $(RM) $@
+ $(SED) -e "s@TEXT_DOMAIN@\"$(TEXT_DOMAIN)\"@" $< > $@
+ $(CHMOD) +x $@
+
+.pm:
+
+
+clean:
+ -$(RM) $(CLEANFILES)
+
+$(ROOTBINPROG): $(PROG)
+ $(INS.file)
+
+$(ROOTLIBABIDIR):
+ $(INS.dir)
+
+$(ROOTLIBABIDIR)/%: %
+ $(INS.file)
+
+%.po: %.pl
+ $(XGETTEXT) $(XGETFLAGS) $<
+ $(RM) $@
+ $(SED) "/^domain/d" messages.po > $@
+ $(RM) messages.po
+
+%.po: %.pm
+ $(XGETTEXT) $(XGETFLAGS) $<
+ $(RM) $@
+ $(SED) "/^domain/d" messages.po > $@
+ $(RM) messages.po
+
+lint:
+
+clobber: clean
+ -$(RM) $(CLOBBERFILES)
+
diff --git a/usr/src/cmd/abi/appcert/scripts/abi_index.pl b/usr/src/cmd/abi/appcert/scripts/abi_index.pl
new file mode 100644
index 0000000..c1ff743
--- /dev/null
+++ b/usr/src/cmd/abi/appcert/scripts/abi_index.pl
@@ -0,0 +1,419 @@
+#!/usr/perl5/bin/perl -w
+#
+# 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
+#
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This utility program reads the contents file to extract Solaris ELF
+# libraries, and then runs pvs(1) on them to find the library versioning
+# information (if any). This info is printed to stdout in an index file
+# format.
+#
+
+require 5.005;
+use strict;
+use locale;
+use POSIX qw(locale_h);
+use Sun::Solaris::Utils qw(textdomain gettext);
+use File::Basename;
+
+use vars qw(
+ @liblist
+ %symlink
+ %inode_hash
+ %fileoutput
+ %didlib
+);
+
+setlocale(LC_ALL, "");
+textdomain(TEXT_DOMAIN);
+
+# parameters for what types of libraries to list out:
+my $must_be_versioned = 0;
+my $must_be_public = 0;
+
+# paths to skip outright.
+my @skip_list = qw(
+ /etc
+ /usr/4lib
+ /usr/perl5
+);
+my $path_skip = join('|', @skip_list);
+$path_skip = qr/^($path_skip)/;
+
+# find library names:
+#
+# We have to use pkgchk -l output (even though it is much slower than
+# parsing /var/sadm/install/contents ourselves) because the contents
+# file will go away or change incompatibly at some point.
+#
+my $old = $ENV{'LC_ALL'};
+$ENV{'LC_ALL'} = 'C';
+my $contents_fh = do { local *FH; *FH };
+open($contents_fh, "/usr/sbin/pkgchk -l|") || die "$!\n";
+if (defined($old)) {
+ $ENV{'LC_ALL'} = $old;
+} else {
+ delete($ENV{'LC_ALL'});
+}
+
+my $pathname = '';
+my $type = '';
+my $link = '';
+my $pkgs = '';
+my $status = '';
+my $inpkgs = 0;
+while (<$contents_fh>) {
+ next if (/^Ex/);
+ chomp;
+ if (/^Pathname:\s*/i) {
+ $pathname = $';
+ $type = '';
+ $link = '';
+ $status = '';
+ $pkgs = '';
+ $inpkgs = 0;
+ next;
+ } elsif (/^Type:\s*/i) {
+ $type = $';
+ next;
+ } elsif (/^Source of link:\s*/i) {
+ $link = $';
+ next;
+ } elsif (/^Referenced by/i) {
+ $inpkgs = 1;
+ } elsif (/^Current status:\s*/i) {
+ $status = $';
+ $inpkgs = 0;
+ next;
+ } elsif (/^\s*$/) {
+ next unless ($pathname =~ m,\.so,);
+ next unless ($pathname =~ m,/lib,);
+ next unless ($pathname =~ m,/lib[^/]*\.so\b,);
+ next unless ($type =~ /regular file|symbolic link/i);
+ next unless ($status =~ /^\s*installed\s*$/);
+ $pathname = trim($pathname);
+ $link = trim($link);
+ filter($pathname, $link, $pkgs);
+ }
+ if ($inpkgs) {
+ $pkgs .= $_ . ' ';
+ }
+}
+close($contents_fh);
+
+# run pvs(1) on the libraries found:
+my $batch = 30; # batch size to use (running in batches is faster).
+
+my @list = ();
+for (my $i = 1; $i <= scalar(@liblist); $i++) {
+ push(@list, $liblist[$i-1]);
+ if ($i % $batch == 0) {
+ do_pvs(@list) if (@list);
+ @list = ();
+ }
+}
+do_pvs(@list) if (@list); # finish any remainder.
+
+exit 0;
+
+#
+# Take a pkgchk -l entry and decide if it corresponds to a Solaris
+# library. If so, save it in the list @liblist, and record info in
+# %symlink & %inode_hash associative arrays as appropriate.
+#
+sub filter
+{
+ my ($path, $link, $pkgs) = @_;
+
+
+ # consider only SUNW packages:
+ return unless ($pkgs =~ /\bSUNW\S+/);
+
+ my $basename;
+
+ $basename = basename($path);
+
+ if ($link ne '') {
+ # include developer build-time symlinks:
+ return unless ($basename =~ /^lib.*\.so[\.\d]*$/);
+ } else {
+ return unless ($basename =~ /^lib.*\.so\.[\.\d]+$/);
+ }
+ return if ($path =~ /$path_skip/);
+
+ return unless (-f $path);
+
+ # inode is used to identify what file a symlink point to:
+ my $inode;
+ $inode = (stat($path))[1];
+ return unless (defined($inode));
+
+ if ($link ne '') {
+ # record info about symlinks:
+ if (exists($symlink{$inode})) {
+ $symlink{$inode} .= ":" . $path;
+ } else {
+ $symlink{$inode} = ":" . $path;
+ }
+ } else {
+ # ordinary file case:
+ $inode_hash{$path} = $inode;
+ push(@liblist, $path);
+ }
+}
+
+#
+# Run pvs(1) on a list of libraries. More than one is done at a time to
+# speed things up.
+#
+# Extracts the version information and passes it to the output() routine
+# for final processing.
+#
+sub do_pvs
+{
+ my (@list) = @_;
+
+ my (%list, $paths, $path, $cnt);
+
+ #
+ # record info about the library paths and construct the list of
+ # files for the pvs command line.
+ #
+ $cnt = 0;
+ $paths = '';
+ foreach $path (@list) {
+ $list{$path} = 1;
+ $paths .= ' ' if ($paths ne '');
+ #
+ # $path should never have single quote in it in
+ # all normal usage. Make sure this is so:
+ #
+ next if ($path =~ /'/);
+ #
+ # quote the filename in case it has meta-characters
+ # (which should never happen in all normal usage)
+ #
+ $paths .= "'$path'";
+ $cnt++;
+ }
+
+ return if ($cnt == 0);
+
+ # set locale to C for running command, since we interpret the output:
+ my $old = $ENV{'LC_ALL'};
+ $ENV{'LC_ALL'} = 'C';
+
+ # get the file(1) output for each item:
+ my $file_fh = do { local *FH; *FH };
+ open($file_fh, "/usr/bin/file $paths 2>&1 |") || die "$!\n";
+ my ($file, $out);
+ while (<$file_fh>) {
+ ($file, $out) = split(/:/, $_, 2);
+ if ($list{$file} && $out =~ /\bELF\b/) {
+ $fileoutput{$file} = $out;
+ }
+ }
+ close($file_fh);
+
+ #
+ # in the case of only 1 item, we place it on the command line
+ # twice to induce pvs(1) to indicate which file it is reporting
+ # on.
+ #
+ if ($cnt == 1) {
+ $paths .= " $paths";
+ }
+
+ #
+ # $paths are entries from /var/sadm/install/contents and
+ # so should not contain spaces or meta characters:
+ #
+ my $pvs_fh = do { local *FH; *FH };
+ open($pvs_fh, "/usr/bin/pvs -dn $paths 2>&1 |") || die "$!\n";
+
+ # reset LC_ALL, if there was any:
+ if (defined($old)) {
+ $ENV{'LC_ALL'} = $old;
+ } else {
+ delete($ENV{'LC_ALL'});
+ }
+
+ my ($pub, $pri, $obs, $evo, $vers, $new_path);
+
+ undef($path);
+
+ # initialize strings used below for appending info to:
+ $pub = '';
+ $pri = '';
+ $obs = '';
+ $evo = '';
+
+ while (<$pvs_fh>) {
+ $_ =~ s/\s*$//;
+ if (m,^([^:]+):$,) {
+ # a new pvs file header, e.g. "/usr/lib/libc.so.1:"
+ if ($list{$1}) {
+ $new_path = $1;
+
+ # output the previous one and reset accumulators:
+ if (defined($path)) {
+ output($path, $pub, $pri, $obs, $evo);
+
+ $pub = '';
+ $pri = '';
+ $obs = '';
+ $evo = '';
+ }
+ $path = $new_path;
+ next; # done with pvs header case
+ }
+ }
+
+ # extract SUNW version head end:
+
+ $vers = trim($_);
+ $vers =~ s/;//g;
+
+ # handle the various non-standard cases in Solaris libraries:
+ if ($vers =~ /^(SUNW.*private|SUNW_XIL_GPI)/i) {
+ $pri .= $vers . ":";
+ } elsif ($vers =~ /^(SUNW_\d|SYSVABI|SISCD)/) {
+ $pub .= $vers . ":";
+ } elsif ($vers =~ /^(SUNW\.\d|SUNW_XIL)/) {
+ $pub .= $vers . ":";
+ } elsif ($vers =~ /^SUNWobsolete/) {
+ $obs .= $vers . ":";
+ } elsif ($vers =~ /^SUNWevolving/) {
+ $evo .= $vers . ":";
+ } else {
+ next;
+ }
+ }
+ close($pvs_fh);
+
+ # output the last one (if any):
+ if (defined($path)) {
+ output($path, $pub, $pri, $obs, $evo);
+ }
+}
+
+#
+# Take the raw library versioning information and process it into index
+# file format and then print it out.
+#
+sub output
+{
+ my ($path, $pub, $pri, $obs, $evo) = @_;
+
+ return if ($didlib{$path}); # skip repeating a library
+
+ # trim off any trailing separators:
+ $pub =~ s/:$//;
+ $pri =~ s/:$//;
+ $obs =~ s/:$//;
+ $evo =~ s/:$//;
+
+ # work out the type of library:
+ my $type;
+ my $defn;
+ my $n;
+ if ($pri && ! $pub && ! $obs && ! $evo) {
+ $type = 'INTERNAL';
+ $defn = 'NO_PUBLIC_SYMS';
+ } elsif ($obs) {
+ $type = 'OBSOLETE';
+ $defn = $obs;
+ } elsif ($pub) {
+ $type = 'PUBLIC';
+ $defn = $pub;
+ if ($defn =~ /:/) {
+ $defn =~ s/:/,/g;
+ $defn = "PUBLIC=$defn";
+ }
+ } elsif ($evo) {
+ $type = 'EVOLVING';
+ $defn = $evo;
+ } elsif (! $pri && ! $pub && ! $obs && ! $evo) {
+ $type = 'UNVERSIONED';
+ $defn = '-';
+ } else {
+ return;
+ }
+
+ # return if instructed to skip either of these cases:
+ if ($must_be_versioned && $type eq 'UNVERSIONED') {
+ return;
+ }
+ if ($must_be_public && $type eq 'INTERNAL') {
+ return;
+ }
+
+
+ # prepare the output line, including any symlink information:
+ my $inode = $inode_hash{$path};
+ my $links;
+ if ($inode && exists($symlink{$inode})) {
+ $links = "${path}$symlink{$inode}";
+ } else {
+ $links = "$path";
+ }
+
+ # count the total number of references:
+ my (@n) = split(/:/, $links);
+ $n = scalar(@n);
+
+ # determine the abi to which the library file belongs:
+ my ($fout, $abi);
+ $abi = 'unknown';
+ $fout = $fileoutput{$path};
+ if ($fout =~ /\bSPARCV9\b/) {
+ $abi = 'sparcv9';
+ } elsif ($fout =~ /\bSPARC/) {
+ $abi = 'sparc';
+ } elsif ($fout =~ /\bAMD64\b/ || $fout =~ /\bELF\s+64-bit\s+LSB\b/) {
+ $abi = 'amd64';
+ } elsif ($fout =~ /\b80386\b/) {
+ $abi = 'i386';
+ }
+ print STDOUT "$abi|$path|$defn|$n|$links\n";
+
+ # record that we did this library so we do not process it a second time.
+ $didlib{$path} = 1;
+}
+
+#
+# Remove leading and trailing spaces.
+#
+sub trim
+{
+ my ($x) = @_;
+ $x =~ s/^\s*//;
+ $x =~ s/\s*$//;
+
+ return $x;
+}
diff --git a/usr/src/cmd/abi/appcert/scripts/appcert.pl b/usr/src/cmd/abi/appcert/scripts/appcert.pl
new file mode 100644
index 0000000..74dec7c
--- /dev/null
+++ b/usr/src/cmd/abi/appcert/scripts/appcert.pl
@@ -0,0 +1,847 @@
+#!/usr/perl5/bin/perl -w
+#
+# 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
+#
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This is the top level script for performing the appcert checks. It
+# reads the command line options, determines list of binaries to check,
+# and then calls symprof (the raw symbol profiler), symcheck (that
+# checks for unstable behavior), and symreport (that constructs and
+# outputs a rollup report)
+#
+
+require 5.005;
+use strict;
+use locale;
+use Getopt::Std;
+use POSIX qw(locale_h);
+use Sun::Solaris::Utils qw(textdomain gettext);
+use File::Basename;
+use File::Path;
+
+use lib qw(/usr/lib/abi/appcert);
+use AppcertUtil;
+
+setlocale(LC_ALL, "");
+textdomain(TEXT_DOMAIN);
+
+use vars qw(
+ @item_list
+ $file_list
+ $do_not_follow_symlinks
+ $modify_ld_path
+ $append_solaris_dirs_to_ld_path
+ $skipped_count
+);
+
+my $caught_signal = 0;
+my $record_binary_call_count = 0;
+
+# The directory where the appcert specific scripts and data reside:
+$appcert_lib_dir = "/usr/lib/abi/appcert";
+
+set_clean_up_exit_routine(\&clean_up_exit);
+
+signals('on', \&interrupted);
+
+get_options();
+
+@item_list = @ARGV; # List of directories and/or objects to check.
+check_item_list();
+
+set_working_dir();
+
+find_binaries(); # Records all of the binary objects to check.
+
+supplement_ld_library_path();
+
+export_vars_to_environment(); # Exports info for our child scripts to use.
+
+run_profiler(); # Run the script symprof.
+
+run_checker(); # Run script symcheck.
+
+run_report_generator(); # Run the script symreport.
+
+my $rc = overall_result_code();
+
+clean_up();
+
+exit $rc;
+
+
+#
+# This subroutine calls getopts() and sets up variables reflecting how
+# we were called.
+#
+sub get_options
+{
+ my %opt;
+
+ getopts('?hnLBSw:f:', \%opt) || (show_usage() && exiter(2));
+
+ if (exists($opt{'?'}) || exists($opt{'h'})) {
+ show_usage();
+ exiter(2);
+ }
+
+ if (exists($opt{'f'})) {
+ $file_list = $opt{'f'};
+ } else {
+ $file_list = '';
+ }
+
+ if (exists($opt{'w'})) {
+ $working_dir = $opt{'w'};
+ } else {
+ $working_dir = '';
+ }
+ if ($working_dir =~ /'/) {
+ #
+ # This character will ultimately cause problems with
+ # system() and pipelines so we exit now.
+ #
+ exiter(sprintf(gettext(
+ "directory contains the single-quote character ': %s\n"),
+ $working_dir));
+ }
+
+ if (defined($opt{'B'})) {
+ $batch_report = 1;
+ } else {
+ $batch_report = 0;
+ }
+
+ if (defined($opt{'n'})) {
+ $do_not_follow_symlinks = 1;
+ } else {
+ $do_not_follow_symlinks = 0;
+ }
+
+ if (defined($opt{'L'})) {
+ $modify_ld_path = 0;
+ } else {
+ $modify_ld_path = 1;
+ }
+
+ if (defined($opt{'S'})) {
+ $append_solaris_dirs_to_ld_path = 1;
+ } else {
+ $append_solaris_dirs_to_ld_path = 0;
+ }
+}
+
+#
+# Performs an initial check to see if the user supplied anything at all
+# to check. Also reads in the file list if the user supplied one via -f <file>
+#
+sub check_item_list
+{
+ # Add the items if the -f flag was used.
+ if ($file_list) {
+ my $file;
+ my $list_fh = do { local *FH; *FH };
+ if (-f $file_list && open($list_fh, "<$file_list")) {
+ while (<$list_fh>) {
+ chomp($file = $_);
+ push(@item_list, $file);
+ }
+ close($list_fh);
+ } else {
+ exiter(nofile($file_list, $!));
+ }
+ }
+
+ return if (@item_list);
+
+ emsg("$command_name: " . gettext(
+ "at least one file or directory to check must be specified.") .
+ "\n\n");
+
+ show_usage();
+ exiter(3);
+}
+
+#
+# This subroutine sets up the working directory, the default something
+# like: /tmp/appcert.<PID>
+#
+sub set_working_dir
+{
+ if ($working_dir) {
+ # working_dir has been set in get_options().
+ if (! -d $working_dir) {
+ if (! mkpath($working_dir) || ! -d $working_dir) {
+ exiter(nocreatedir($working_dir, $!));
+ }
+ } else {
+ if (! dir_is_empty($working_dir)) {
+ # create a subdir of it for our use.
+ $working_dir = create_tmp_dir($working_dir);
+ }
+ }
+ } else {
+ # Default case: will create, e.g., /tmp/appcert.12345
+ $working_dir = create_tmp_dir();
+ }
+
+ if (! -d $working_dir) {
+ # We have no working directory.
+ exiter(nocreatedir($working_dir));
+ }
+
+ #
+ # Create a subdirectory of working_dir that will contain all of
+ # the object subdirs.
+ #
+ my $dir = "$working_dir/$object_dir";
+ if (! mkpath($dir) || ! -d $dir) {
+ exiter(nocreatedir($dir, $!));
+ }
+ #
+ # Make a tmp subdirectory for small temporary work. It is
+ # preferred to have it on tmpfs (especially not NFS) for
+ # performance reasons.
+ #
+ $tmp_dir = "/tmp/${command_name}_tmp.$$";
+ if (-d $tmp_dir) {
+ exiter(nocreatedir("$tmp_dir", $!));
+ }
+ if (! mkpath($tmp_dir, 0, 0700) || ! -d $tmp_dir) {
+ emsg("%s", nocreatedir($tmp_dir, $!));
+ # fall back to our output dir (which could have slow access)
+ $tmp_dir = "$working_dir/tmp";
+ if (! mkpath($tmp_dir)) {
+ exiter(nocreatedir($tmp_dir, $!));
+ }
+ }
+
+ if (! -d $tmp_dir) {
+ exiter(nocreatedir($tmp_dir, $!));
+ }
+}
+
+#
+# Top level function to find all the binaries to be checked. Calls
+# record_binary() to do the actual deciding and recording.
+#
+# The array @item_list contains all the items to find.
+#
+sub find_binaries
+{
+ $binary_count = 0;
+
+ my $skipped_file = "$working_dir/Skipped";
+ my $skipped_fh = do { local *FH; *FH };
+ open($skipped_fh, ">$skipped_file") ||
+ exiter(nofile($skipped_file, $!));
+
+ $skipped_count = 0;
+
+ my ($item, $args, $file);
+ emsg("\n" . gettext(
+ "finding executables and shared libraries to check") . " ...\n");
+
+ $args = '';
+ $args .= '-follow ' unless ($do_not_follow_symlinks);
+ $args .= '-type f -print';
+
+ my $quote_fmt = gettext(
+ "skipping: item contains the single-quote character ': %s\n");
+
+ foreach $item (@item_list) {
+ if (! -e $item) {
+ emsg(gettext("skipping: %s: %s\n"), $item, $!);
+ print $skipped_fh "$item: no_exist\n";
+ $skipped_count++;
+ next;
+ } elsif ($item =~ /'/) {
+ emsg($quote_fmt, $item);
+ print $skipped_fh "$item: item_has_bad_char\n";
+ $skipped_count++;
+ next;
+ }
+ # note that $item does not contain a single-quote.
+ my $find_fh = do { local *FH; *FH };
+ open($find_fh, "$cmd_find '$item' $args|") ||
+ exiter(norunprog("$cmd_find '$item' $args", $!));
+
+ while (<$find_fh>) {
+ chomp($file = $_);
+ #
+ # We are free to remove leading "./". This will
+ # minimize directory names we create that would
+ # start with a dot.
+ #
+ $file =~ s,^\./,,;
+
+ next if ($file eq '');
+
+ record_binary($file, $skipped_fh);
+ }
+ close($find_fh);
+ }
+
+ if ($binary_count == 0) {
+ exiter("$command_name: " . gettext(
+ "no checkable binary objects were found."), 3);
+ }
+
+ if ($skipped_count == 0) {
+ print $skipped_fh "# NO_FILES_WERE_SKIPPED\n";
+ }
+ close($skipped_fh);
+}
+
+#
+# This subroutine will determine if a binary is checkable.
+#
+# If so, it will reserve a directory for its output in the $working_dir
+# location, and store the output of a number of commands there.
+#
+sub record_binary
+{
+ my ($file, $skipped_fh) = @_;
+
+ if ((++$record_binary_call_count % 500) == 0) {
+ #
+ # This indicates are being called many times for a large
+ # product. Clear out our caches.
+ #
+ purge_caches();
+ }
+
+ #
+ # Check if the object exists and is regular file. Note that
+ # this test also passes a symlink as long as that symlink
+ # ultimately refers to a regular file.
+ #
+ if (! -f $file) {
+ emsg(gettext("skipping: not a file: %s\n"), $file);
+ print $skipped_fh "$file: not_a_file\n";
+ $skipped_count++;
+ return 0;
+ }
+
+ # Check if it is readable:
+ if (! -r $file) {
+ emsg(gettext("skipping: cannot read: %s\n"), $file);
+ print $skipped_fh "$file: unreadable\n";
+ $skipped_count++;
+ return 0;
+ }
+
+ #
+ # Since the filename will be used as operands passed to utility
+ # commands via the shell, we exclude at the outset certain meta
+ # characters in the filenames.
+ #
+ my $quote_fmt = gettext(
+ "skipping: filename contains the single-quote character: ': %s\n");
+ if ($file =~ /'/) {
+ emsg($quote_fmt, $file);
+ print $skipped_fh "$file: filename_has_bad_char\n";
+ $skipped_count++;
+ return 0;
+ }
+
+ my $newline_fmt = gettext(
+ "skipping: filename contains the newline character: \\n: %s\n");
+ if ($file =~ /\n/) {
+ emsg($newline_fmt, $file);
+ print $skipped_fh "$file: filename_has_bad_char\n";
+ $skipped_count++;
+ return 0;
+ }
+
+ my $pipe_fmt = gettext(
+ "skipping: filename contains the pipe character: \|: %s\n");
+ if ($file =~ /\|/) {
+ emsg($pipe_fmt, $file);
+ print $skipped_fh "$file: filename_has_bad_char\n";
+ $skipped_count++;
+ return 0;
+ }
+
+ my $file_output;
+
+ # Run the file(1) command on it.
+
+ c_locale(1);
+ # note that $file does not contain a single-quote.
+ $file_output = `$cmd_file '$file' 2>/dev/null`;
+ c_locale(0);
+
+ if ($file_output =~ /script$/) {
+ $file_output =~ s/:\s+/: /;
+ $file_output =~ s/: /: script /;
+ print $skipped_fh "$file_output";
+
+ #
+ # again now without the c_locale() setting:
+ # note that $file does not contain a single-quote.
+ #
+ $file_output = `$cmd_file '$file' 2>/dev/null`;
+ $file_output =~ s/:\s+/: /;
+ emsg(gettext("skipping: %s"), $file_output);
+ $skipped_count++;
+ return 0;
+ }
+
+ # create ELF and a.out matching regex:
+ my $object_match =
+ 'ELF.*executable.*dynamically' . '|' .
+ 'ELF.*dynamic lib' . '|' .
+ 'ELF.*executable.*statically' . '|' .
+ 'Sun demand paged SPARC.*dynamically linked' . '|' .
+ 'Sun demand paged SPARC executable' . '|' .
+ 'pure SPARC executable' . '|' .
+ 'impure SPARC executable';
+
+ #
+ # Note that we let the "statically linked" binaries through
+ # here, but will catch them later in the profiler and checker.
+ #
+
+ if ($file_output !~ /$object_match/io) {
+ # it is not an ELF object file and so does not interest us.
+ return 0;
+ }
+
+ my $exec_fmt = gettext(
+ "skipping: must have exec permission to be checked: %s\n");
+ if (! -x $file) {
+ #
+ # It interests us, but the execute bit not set. Shared
+ # objects will be let through here since ldd will still
+ # work on them (since it uses lddstub). Otherwise, we
+ # cannot check it.
+ #
+ if (! is_shared_object($file)) {
+ # warn the user exec bit should be set:
+ emsg($exec_fmt, $file);
+ print $skipped_fh "$file: no_exec_permission\n";
+ $skipped_count++;
+ return 0;
+ }
+ }
+
+ #
+ # Rather than let ldd fail later on in symprof, we check the
+ # arch here to make sure it matches $uname_p. If it does not
+ # match, we anticipate a 64-bit application and so we
+ # immediately test how ldd will handle it (kernel might be
+ # 32-bit, etc).
+ #
+ my ($arch, $type, $wordsize, $endian, $e_machine) = bin_type($file);
+
+ if ($arch !~ /^${uname_p}$/io) {
+ my ($ldd_output, $ldd_output2);
+
+ #
+ # Now run ldd on it to see how things would go. If it
+ # fails we must skip it.
+ #
+ c_locale(1);
+ # note that $file does not contain single-quote
+ $ldd_output = `$cmd_ldd '$file' 2>&1 1>/dev/null`;
+ c_locale(0);
+ if ($? != 0) {
+ # note that $file does not contain a single-quote
+ $ldd_output2 = `$cmd_ldd '$file' 2>&1 1>/dev/null`;
+ $ldd_output =~ s/\n.*$//;
+ $ldd_output2 =~ s/\n.*$//;
+ if ($ldd_output !~ /wrong class/) {
+ $ldd_output = "$file: " . sprintf(
+ gettext("ldd failed for arch: %s"), $arch);
+ $ldd_output2 = $ldd_output;
+ } else {
+ $ldd_output .= " ($arch)";
+ $ldd_output2 .= " ($arch)";
+ }
+ $ldd_output =~ s/:\s+/: /;
+ $ldd_output2 =~ s/:\s+/: /;
+ emsg(gettext("skipping: %s\n"), $ldd_output2);
+ $ldd_output =~ s/: /: ldd_failed /;
+ print $skipped_fh "$ldd_output\n";
+ $skipped_count++;
+ return 0;
+ }
+ }
+
+ # From this point on, object is one we decided to check.
+
+ # Create the directory name for this object:
+ my $dirname = object_to_dir_name($file);
+ my $dirpath = "$working_dir/$dirname";
+ my $early_fmt = gettext(
+ "skipping: %s referenced earlier on the command line\n");
+ if (-e $dirpath) {
+ #
+ # Directory already exists. We assume this means the
+ # user listed it twice (possibly indirectly via "find").
+ #
+ emsg($early_fmt, $file);
+ return 0;
+ }
+
+ if (! mkdir($dirpath, 0777)) {
+ exiter(nocreatedir($dirpath, $!));
+ }
+
+ $binary_count++;
+
+ # Record binary object's location:
+ my $path_fh = do { local *FH; *FH };
+ open($path_fh, ">$dirpath/info.path") ||
+ exiter(nofile("$dirpath/info.path", $!));
+ print $path_fh $file, "\n";
+ close($path_fh);
+
+ #
+ # Record /usr/bin/file output. Note that the programmatical way
+ # to access this info is through the command cmd_output_file().
+ #
+ my $file_fh = do { local *FH; *FH };
+ open($file_fh, ">$dirpath/info.file") ||
+ exiter(nofile("$dirpath/info.file", $!));
+ print $file_fh $file_output;
+ close($file_fh);
+
+ #
+ # Record dump -Lv output. Note that the programmatical way to
+ # access this info is through the command cmd_output_dump().
+ #
+ my $dump_fh = do { local *FH; *FH };
+ open($dump_fh, ">$dirpath/info.dump") ||
+ exiter(nofile("$dirpath/info.dump", $!));
+
+ my $dump_output;
+ c_locale(1);
+ # note that $file does not contain a single-quote
+ $dump_output = `$cmd_dump -Lv '$file' 2>&1`;
+ c_locale(0);
+ print $dump_fh $dump_output;
+ close($dump_fh);
+
+ #
+ # Record arch and etc binary type.
+ #
+ my $arch_fh = do { local *FH; *FH };
+ open($arch_fh, ">$dirpath/info.arch") ||
+ exiter(nofile("$dirpath/info.arch", $!));
+
+ if ($arch eq 'unknown') {
+ my $tmp = $file_output;
+ chomp($tmp);
+ emsg(gettext("warning: cannot determine arch: %s\n"), $tmp);
+ }
+
+ print $arch_fh "ARCH: $arch\n";
+ print $arch_fh "TYPE: $type\n";
+ print $arch_fh "WORDSIZE: $wordsize\n";
+ print $arch_fh "BYTEORDER: $endian\n";
+ print $arch_fh "E_MACHINE: $e_machine\n";
+ close($arch_fh);
+
+ # Record the file -> directory name mapping in the index file.
+ my $index_file = "$working_dir/Index";
+ my $index_fh = do { local *FH; *FH };
+ open($index_fh, ">>$index_file") ||
+ exiter(nofile($index_file, $!));
+ print $index_fh "$file => $dirname\n";
+ close($index_fh);
+
+ return 1;
+}
+
+#
+# Prints the usage statement to standard out.
+#
+sub show_usage
+{
+ emsg(gettext(
+ "usage: appcert [ -nBLS ] [ -f file ] [ -w dir ] { obj | dir } ...\n" .
+ " Examine binary object files for use of private Solaris\n" .
+ " interfaces, unstable use of static linking, and other\n" .
+ " unstable practices.\n")
+ );
+}
+
+#
+# Examines the set of binaries to be checked and notes which ones are
+# shared libraries. Constructs a LD_LIBRARY_PATH that would find ALL of
+# these shared objects. The new directories are placed at the END of the
+# current LD_LIBRARY_PATH (if any).
+#
+sub supplement_ld_library_path
+{
+ my (@orig, @add_product, @add_solaris, %ldpath);
+
+ # First, note the current LD_LIBRARY_PATH parts:
+
+ my $dirname;
+ if (defined($ENV{'LD_LIBRARY_PATH'})) {
+ foreach $dirname (split(/:/, $ENV{'LD_LIBRARY_PATH'})) {
+ if (! exists($ldpath{$dirname})) {
+ push(@orig, $dirname);
+ $ldpath{$dirname} = 1;
+ }
+ }
+ }
+
+ # Next, search for ELF shared objects.
+ my ($dir, $path);
+
+ if ($modify_ld_path) {
+ while (defined($dir = next_dir_name())) {
+ $path = dir_name_to_path($dir);
+
+ $dirname = dirname($path);
+ next if (exists($ldpath{$dirname}));
+
+ #
+ # A colon ":" in directory name is cannot be
+ # accepted because that is the LD_LIBRARY_PATH
+ # separator.
+ #
+ next if ($dirname =~ /:/);
+
+ if (is_shared_object($path)) {
+ if (! exists($ldpath{$dirname})) {
+ push(@add_product, $dirname);
+ $ldpath{$dirname} = 1;
+ }
+ }
+ }
+ }
+
+ if ($append_solaris_dirs_to_ld_path) {
+ foreach $dirname (split(/:/, $solaris_library_ld_path)) {
+ if (! exists($ldpath{$dirname})) {
+ push(@add_solaris, $dirname);
+ $ldpath{$dirname} = 1;
+ }
+ }
+ }
+
+ # modify the LD_LIBRARY_PATH:
+ if (@add_product || @add_solaris) {
+ $ENV{'LD_LIBRARY_PATH'} =
+ join(':', (@orig, @add_product, @add_solaris));
+ }
+
+ emsg("\n");
+ if (@add_product) {
+ emsg(gettext(
+ "Shared libraries were found in the application and the\n" .
+ "following directories are appended to LD_LIBRARY_PATH:\n"
+ ) . "\n");
+
+ foreach $dir (@add_product) {
+ $dir = "./$dir" unless ($dir =~ m,^/,);
+ emsg(" $dir\n");
+ }
+ emsg("\n");
+ }
+
+ if (@add_solaris) {
+ emsg(gettext(
+ "These Solaris library directories are being appended\n" .
+ "to LD_LIBRARY_PATH:\n") . "\n");
+
+ foreach $dir (@add_solaris) {
+ emsg(" $dir\n");
+ }
+ emsg("\n");
+ }
+}
+
+#
+# Everything is correctly exported by now, and so we just run "symprof".
+# It is run in batches of $block_size binaries to minimize the effect of
+# memory usage caused by huge binaries in the product to be checked.
+#
+sub run_profiler
+{
+ my $block_size = 20;
+
+ my $i = 0;
+
+ # record old values of the blocks (if any)
+ my $env_min = $ENV{'AC_BLOCK_MIN'};
+ my $env_max = $ENV{'AC_BLOCK_MAX'};
+
+ while ($i < $binary_count) { # do each block
+ # export our symprof values of the block limits
+ $ENV{'AC_BLOCK_MIN'} = $i;
+ $ENV{'AC_BLOCK_MAX'} = $i + $block_size;
+
+ run_symprof();
+
+ $i += $block_size;
+ }
+
+ # restore old values of the blocks (if any)
+ if (defined($env_min)) {
+ $ENV{'AC_BLOCK_MIN'} = $env_min;
+ } else {
+ delete $ENV{'AC_BLOCK_MIN'};
+ }
+ if (defined($env_max)) {
+ $ENV{'AC_BLOCK_MAX'} = $env_max;
+ } else {
+ delete $ENV{'AC_BLOCK_MAX'};
+ }
+}
+
+#
+# Sub that actually runs "symprof".
+#
+sub run_symprof
+{
+ system("$appcert_lib_dir/symprof");
+ if ($? != 0) {
+ emsg("%s", utilityfailed("symprof"));
+ clean_up_exit(1);
+ }
+}
+
+#
+# Sub to run "symcheck".
+#
+sub run_checker
+{
+ system("$appcert_lib_dir/symcheck");
+ if ($? != 0) {
+ emsg("%s", utilityfailed("symcheck"));
+ clean_up_exit(1);
+ }
+}
+
+#
+# Sub to run "symreport".
+#
+sub run_report_generator
+{
+ system("$appcert_lib_dir/symreport");
+ if ($? != 0) {
+ emsg("%s", utilityfailed("symreport"));
+ clean_up_exit(1);
+ }
+}
+
+#
+# General routine to be called if one of our utility programs (symprof,
+# symcheck, symreport) failed (that is, return != 0). returns the
+# formatted error message string to pass to the user.
+#
+sub utilityfailed
+{
+ my ($prog) = @_;
+ my $fmt;
+ $fmt = "\n *** " . gettext("utility program failed: %s\n");
+ return sprintf($fmt, $prog);
+}
+
+#
+# Does the cleanup and then exits with return code $rc. The utility
+# subroutine exiter() will call this subroutine. No general cleanup is
+# performed if exiting with error ($rc > 0) so that the user can examine
+# at the output files, etc.
+#
+sub clean_up_exit
+{
+ my ($rc) = @_;
+
+ if ($rc != 0) {
+ working_dir_msg();
+ } else {
+ clean_up();
+ }
+
+ exit $rc;
+}
+
+#
+# General cleanup routine.
+#
+sub clean_up
+{
+ if (-d $tmp_dir && ($tmp_dir !~ m,^/+$,)) {
+ rmdir($tmp_dir);
+ }
+}
+
+#
+# Routine that is called when an error has occurred. It indicates to
+# user where the working and/or temporary directory is and that they are
+# not being removed.
+#
+sub working_dir_msg
+{
+
+ my @dirlist;
+ emsg("\n");
+ if (defined($working_dir) && -d $working_dir) {
+ push(@dirlist, $working_dir);
+ }
+ if (defined($tmp_dir) && -d $tmp_dir) {
+ push(@dirlist, $tmp_dir);
+ }
+
+ return if (! @dirlist);
+
+ emsg(gettext(
+ "Note that the temporary working directories still exist:") .
+ "\n\n");
+
+ my $dir;
+ # show the user explicitly which directories remains:
+ foreach $dir (@dirlist) {
+ system($cmd_ls, '-ld', $dir);
+ }
+
+ emsg("\n");
+}
+
+#
+# Signal handler for interruptions (E.g. Ctrl-C SIGINT).
+#
+sub interrupted
+{
+ $SIG{$_[0]} = 'IGNORE';
+
+ exit 1 if ($caught_signal);
+ $caught_signal = 1;
+
+ signals('off');
+ emsg("\n** " . gettext("interrupted") . " **\n");
+
+ clean_up_exit(1);
+}
diff --git a/usr/src/cmd/abi/appcert/scripts/symcheck.pl b/usr/src/cmd/abi/appcert/scripts/symcheck.pl
new file mode 100644
index 0000000..1d77f34
--- /dev/null
+++ b/usr/src/cmd/abi/appcert/scripts/symcheck.pl
@@ -0,0 +1,1309 @@
+#!/usr/perl5/bin/perl -w
+#
+# 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
+#
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This utility program loads the unstable behavior databases, then reads
+# the symprof output for each binary, and record any detected unstable
+# behavior in the binary's output directory.
+#
+
+require 5.005;
+use strict;
+use locale;
+use POSIX qw(locale_h);
+use Sun::Solaris::Utils qw(textdomain gettext);
+use File::Basename;
+use File::Path;
+
+use lib qw(/usr/lib/abi/appcert);
+use AppcertUtil;
+
+setlocale(LC_ALL, "");
+textdomain(TEXT_DOMAIN);
+
+use vars qw(
+ $LIBC
+ $tmp_check_dir
+ $binaries_checked_count
+ $misc_check_databases_loaded_ok
+ %load_model_default
+ %load_error
+ %model_loaded
+ %model
+ %is_system_library_cache
+);
+
+set_clean_up_exit_routine(\&clean_up_exit);
+
+initialize_variables();
+
+import_vars_from_environment();
+
+signals('on', \&interrupted);
+
+set_working_dir();
+
+load_model_index();
+
+check_objects();
+
+clean_up();
+
+exit 0;
+
+#
+# Set up any variables.
+#
+sub initialize_variables
+{
+ # Here is what we call libc:
+ $LIBC = '/usr/lib/libc.so.1';
+}
+
+#
+# working_dir has been imported by import_vars_from_environment()
+# A sanity check is performed here to make sure it exists.
+#
+sub set_working_dir
+{
+ if (! defined($working_dir) || ! -d $working_dir) {
+ exiter("$command_name: " . sprintf(gettext(
+ "cannot locate working directory: %s\n"), $working_dir));
+ }
+}
+
+#
+# Called when interrupted by a signal.
+#
+sub interrupted
+{
+ $SIG{$_[0]} = 'DEFAULT';
+ signals('off');
+ clean_up_exit(1);
+}
+
+#
+# Does the cleanup then exit with return code $rc. Note: The utility
+# routine exiter() will call this routine.
+#
+sub clean_up_exit
+{
+ my ($rc) = @_;
+ $rc = 0 unless ($rc);
+
+ clean_up();
+ exit $rc;
+}
+
+#
+# General cleanup activities are placed here. There may not be an
+# immediate exit after this cleanup.
+#
+sub clean_up
+{
+ if (defined($tmp_check_dir) && -d $tmp_check_dir) {
+ rmtree($tmp_check_dir);
+ }
+}
+
+#
+# Top level routine to initialize databases and then loop over the
+# objects and call the checking routines on each one.
+#
+sub check_objects
+{
+ # Make a tmp dir for the checking work.
+ $tmp_check_dir = create_tmp_dir($tmp_dir);
+
+ if (! -d $tmp_check_dir) {
+ exiter(nocreatedir($tmp_check_dir, $!));
+ }
+
+ emsg("\n" . gettext(
+ "checking binary objects for unstable practices") . " ...\n\n");
+
+ my ($dir, $path_to_object);
+
+ #
+ # Loop over each object item in the working_dir.
+ # - $dir will be each one of these object directories.
+ # - $path_to_object will be the corresponding actual path
+ # to the the binary to be checked.
+ # Output will be placed down in $dir, e.g. "$dir/check.foo"
+ #
+
+ $binaries_checked_count = 0;
+
+ #
+ # We need to load the Misc Databases to get any modifications to
+ # the symbol database. E.g. gethostname should be public.
+ #
+ $misc_check_databases_loaded_ok = load_misc_check_databases();
+
+ while (defined($dir = next_dir_name())) {
+
+ # Map object output dir to actual path of the object:
+ $path_to_object = dir_name_to_path($dir);
+
+ if (! -f $path_to_object) {
+ exiter(nopathexist($path_to_object, $!));
+ }
+
+ # Check it:
+ emsg(gettext("checking: %s\n"), $path_to_object);
+
+ static_check_object($path_to_object, $dir);
+ dynamic_check_object($path_to_object, $dir);
+ }
+
+ if ($binaries_checked_count == 0) {
+ exiter("$command_name: " . gettext(
+ "no binary objects where checked."));
+ }
+
+ # Do additional heuristic checks of unstable behavior:
+ perform_misc_checks();
+
+ clean_up(); # Remove any tmp dirs and files.
+}
+
+#
+# Reads in the static profile (i.e. the symbols exported by bin in
+# .text section) and calls the static archive checking routine.
+#
+sub static_check_object
+{
+ my ($path_to_object, $dir) = @_;
+
+ # The profile output file created by static_profile() in symprof.
+
+ my $profile_file = "$dir/profile.static";
+
+ my $err_fmt = gettext(
+ "binary object %s has no static profile: %s: %s\n");
+ if (! -f $profile_file) {
+ emsg("$command_name: " . $err_fmt, $path_to_object,
+ $profile_file, $!);
+ return 0;
+ }
+
+ my $profile_fh = do { local *FH; *FH };
+ if (! open($profile_fh, "<$profile_file")) {
+ exiter(nofile($profile_file, $!));
+ }
+
+ my ($profile, $lib, $lib2, $base, %libs_needed);
+
+ my $completely_statically_linked = 0;
+
+ while (<$profile_fh>) {
+ $profile .= $_;
+ if (/^\s*#dtneeded:\s*(.*)$/) {
+ #
+ # record the bare name, e.g. "libc" of the
+ # (direct) dtneededs.
+ #
+ foreach $lib (split(/\s+/, $1)) {
+ next if ($lib eq '');
+ $base = $lib;
+ # record it as libc.so.1 -> libc
+ $base =~ s/\.so\..*$//;
+ $base =~ s/\.so$//;
+ $libs_needed{$base} = $lib;
+ $libs_needed{basename($base)} = $lib;
+ }
+ } elsif (/^\s*#SKIPPED_TEST:\s+STATICALLY_LINKED/) {
+ #
+ # Record statical linking if it takes place
+ # since it indicates to skip the test.
+ #
+ $completely_statically_linked = 1;
+ }
+ }
+ close($profile_fh);
+
+ my $problems = "$dir/check.problems";
+
+ my $problems_fh = do { local *FH; *FH };
+ if (! open($problems_fh, ">>$problems")) {
+ exiter(nofile($problems, $!));
+ }
+
+ if ($completely_statically_linked) {
+ print $problems_fh "STATIC: COMPLETELY_STATIC" . "\n";
+ }
+
+ my (%saw_lib);
+ if (! defined($profile)) {
+ close($problems_fh);
+ return;
+ }
+ foreach $lib (lib_static_check($profile)) {
+ #
+ # lib_static_check returns a list of statically linked
+ # libraries, however to be on the safe side we will skip
+ # false positives our dtneeded's show they are really
+ # dynamically linked in.
+ #
+
+ next if ($libs_needed{$lib});
+ next if ($libs_needed{basename($lib)});
+ next if ($saw_lib{basename($lib)}++);
+
+ $lib2 = $lib;
+ $lib2 =~ s/\.a$//;
+ next if ($libs_needed{$lib2});
+ next if ($libs_needed{basename($lib2)});
+
+ # Otherwise, record in the problems file:
+ print $problems_fh "STATIC: LINKED_ARCHIVE $lib" . "\n";
+ }
+ close($problems_fh);
+}
+
+#
+# Takes as input the static profile (e.g. the .text symbols) and returns
+# a list of suspected statically linked Solaris archive libraries.
+#
+sub lib_static_check
+{
+ my ($profile) = @_;
+
+ my ($line, $area, $extent, $type, $sym, $obj);
+
+ my (%symbols);
+
+ #
+ # Working on lines like:
+ # /bin/ftp|TEXT|GLOB|FUNC|glob
+ # /bin/ftp|TEXT|GLOB|FUNC|help
+ #
+
+ # First record all the symbols in the TEXT area:
+
+ foreach $line (split(/\n/, $profile)) {
+ next unless ($line =~ /\bTEXT\b/);
+ ($obj, $area, $extent, $type, $sym) = split(/\|/, $line);
+
+ $symbols{$sym} = 1;
+ }
+
+ my (@static_libs);
+
+ # Next, check against the library heuristics for static linking:
+
+ # libc.a:
+
+ if (exists($symbols{'_exit'})) {
+ push(@static_libs, "/usr/lib/libc.a");
+ }
+
+ # libsocket.a:
+
+ if (exists($symbols{'socket'}) && exists($symbols{'_socket'}) &&
+ exists($symbols{'bind'}) && exists($symbols{'_bind'}) &&
+ exists($symbols{'connect'}) && exists($symbols{'_connect'})) {
+ push(@static_libs, "/usr/lib/libsocket.a");
+ }
+
+ # libnsl.a:
+
+ if (exists($symbols{'_xti_bind'}) && exists($symbols{'_xti_connect'}) &&
+ exists($symbols{'_tx_bind'}) && exists($symbols{'_tx_connect'})) {
+ push(@static_libs, "/usr/lib/libnsl.a");
+ }
+
+ return @static_libs;
+}
+
+#
+# Reads in the dynamic profile from the object's output directory.
+# Loads any needed public/private Solaris library symbol models.
+# Records unstable use of any private Solaris symbols in the object's
+# output directory.
+#
+sub dynamic_check_object
+{
+ my ($path_to_object, $dir) = @_;
+
+ # Location of the dynamic profile output:
+ my $profile_file = "$dir/profile.dynamic";
+
+ my $err_fmt = gettext(
+ "binary object %s has no dynamic profile: %s: %s\n");
+ if (! -f $profile_file) {
+ emsg("$command_name: " . $err_fmt, $path_to_object,
+ $profile_file, $!);
+ return 0;
+ }
+
+ my $profile_fh = do { local *FH; *FH };
+ if (! open($profile_fh, "<$profile_file")) {
+ exiter(nofile($profile_file, $!));
+ }
+
+ $binaries_checked_count++;
+
+ #
+ # Variables to hold temporary items:
+ #
+ # %library_list will be a hash of "to" libraries we need to load.
+ # @symbol_list will be an array of the "lib|sym" pairs.
+ #
+
+ my (%library_list, @symbol_list, @unbound_list);
+ my ($to, $sym, $from, $binary, $line);
+
+ my ($to_is_sys_lib, $from_is_sys_lib);
+
+ #
+ # profile lines look like:
+ # /bin/ftp|*DIRECT*|libsocket.so.1|socket
+ # /bin/ftp|libnsl.so.1|libc.so.1|mutex_lock
+ #
+ # or:
+ #
+ # /bin/ftp|*DIRECT*|/usr/lib/libsocket.so.1|socket
+ # /bin/ftp|/usr/lib/libnsl.so.1|/usr/lib/libc.so.1|mutex_lock
+ #
+
+ my ($abi, $type, $wordsize, $endian, $e_machine) =
+ bin_type($path_to_object);
+
+ #
+ # Setting abi to 'any' will allow continuation when
+ # we encounter an abi we do not recognize.
+ #
+ if (! defined($abi) || $abi eq 'unknown') {
+ $abi = 'any';
+ } else {
+ #
+ # Always try to load libc. This will be used for symbol
+ # migration to libc checks.
+ #
+ if (! exists($load_model_default{$abi})) {
+ load_model($LIBC, $abi);
+ }
+ $load_model_default{$abi} = 1;
+ }
+
+ my $dynamic_bindings_count = 0;
+ my $no_bindings_msg;
+
+ while (<$profile_fh>) {
+ chomp;
+
+ if (/^\s*#/) {
+ if (/NO_BINDINGS_FOUND\s*(.*)$/) {
+ my $msg = $1;
+ if ($msg =~ /^\s*$/) {
+ $no_bindings_msg = 'NO_SYMBOL_BINDINGS_FOUND';
+ } else {
+ $no_bindings_msg = $msg;
+ }
+ }
+ next;
+ }
+
+ ($binary, $from, $to, $sym) = split(/\|/, $_, 4);
+
+ $dynamic_bindings_count++;
+
+ # Skip the checking of reverse calls:
+ next if ($from eq "*REVERSE*");
+
+ # Skip the checking of special symbols:
+ next if (exists($skip_symbols{$sym}));
+
+ # Accumulate unbounds, but otherwise skip them:
+ if ($to eq "*UNBOUND*") {
+ push(@unbound_list, "$from|$sym");
+ next;
+ }
+
+ # Record if the "to" object is a system library:
+ $to_is_sys_lib = is_system_library($to, $abi);
+
+ if ($from eq "*DIRECT*") {
+ $from_is_sys_lib = 0;
+ } else {
+ #
+ # Otherwise we may check its calls. See if it is
+ # a system lib:
+ #
+ $from_is_sys_lib = is_system_library($from, $abi);
+ }
+
+ #
+ # We will pass judgement on *DIRECT* calls and indirect
+ # calls from a library we do not recognize.
+ #
+ if ($from_is_sys_lib) {
+ next;
+ }
+ if (! $to_is_sys_lib) {
+ # Call to a middleware or supporting library.
+ next;
+ }
+
+ $library_list{$to} = 1;
+ push(@symbol_list, "$from|$to|$abi|$sym");
+ }
+
+ close($profile_fh);
+
+ my $file;
+
+ my $problems_fh = do { local *FH; *FH };
+ if ($dynamic_bindings_count == 0 && defined($no_bindings_msg)) {
+ $file = "$dir/check.problems";
+
+ if (! open($problems_fh, ">>$file")) {
+ exiter(nofile($file, $!));
+ }
+
+ print $problems_fh "DYNAMIC: NO_DYNAMIC_BINDINGS_FOUND" .
+ " $no_bindings_msg\n";
+ close($problems_fh);
+ return;
+ }
+
+ my ($lib, $str);
+
+ $file = "$dir/check.dynamic.abi_models";
+ my $model_info_fh = do { local *FH; *FH };
+ if (! open($model_info_fh, ">$file")) {
+ exiter(nofile($file, $!));
+ }
+
+ # Load all the needed library models:
+ my ($s1, $s2);
+ $s1 = ",NO_PUBLIC/PRIVATE_MODEL_FOUND-SKIPPING_CHECK_FOR_THIS_LIBRARY";
+ $s2 = "ERROR_LOADING_PUBLIC/PRIVATE_MODEL";
+
+ foreach $lib (keys %library_list) {
+ if (! load_model($lib, $abi) && ! $load_error{"$lib|$abi"}) {
+ $load_error{"$lib|$abi"} = 1;
+ }
+ $str = $model_loaded{"$lib|$abi"};
+ if ($str eq '__FAILED__') {
+ $str .= $s1;
+ } elsif (! $str) {
+ $str = $s2;
+ }
+ print $model_info_fh "$lib:$str\n";
+ }
+ close($model_info_fh);
+
+ my ($lib_abi_sym, $class, %result_list);
+
+ my ($l, $a, $s);
+ foreach $lib_abi_sym (@symbol_list) {
+
+ ($from, $lib_abi_sym) = split(/\|/, $lib_abi_sym, 2);
+
+ ($l, $a, $s) = split(/\|/, $lib_abi_sym);
+
+ if (! exists($model{$lib_abi_sym})) {
+ #
+ # Check the library. If it is not in
+ # model_loaded, then we claim it is not a
+ # library we are interested in.
+ #
+ next if (! exists($model_loaded{"$l|$a"}));
+ next if ($model_loaded{"$l|$a"} eq '__FAILED__');
+
+ # it is an unrecognized symbol:
+ $result_list{'unrecognized'} .=
+ "$from|$lib_abi_sym" . "\n";
+ next;
+ }
+
+ # N.B. $lib_abi_sym and $l may have been altered above.
+ $class = $model{$lib_abi_sym};
+ $line = "$path_to_object|$a|$from|$l|$class|$s" . "\n";
+
+ if ($class !~ /^(public|private|unclassified)$/) {
+ exiter("$command_name" . sprintf(gettext(
+ "unrecognized symbol class: %s"), $class));
+ }
+
+ $result_list{$class} .= $line;
+ }
+
+ if (@unbound_list) {
+ my $ldd_file = "$dir/profile.dynamic.ldd";
+ my $tmp;
+ if (-f $ldd_file) {
+ my $ldd_info_fh = do { local *FH; *FH };
+ if (! open($ldd_info_fh, "<$ldd_file")) {
+ exiter(nofile($ldd_file, $!));
+ }
+ while (<$ldd_info_fh>) {
+ $tmp .= '# ' . $_ if (/not\s+found/);
+ }
+ close($ldd_info_fh);
+ }
+ if (defined($tmp)) {
+ $result_list{'unbound'} = $tmp;
+ }
+ $result_list{'unbound'} .= join("\n", @unbound_list) . "\n";
+ }
+
+ my $count;
+
+ my @classes = qw(private public unbound unclassified unrecognized);
+
+ foreach $class (@classes) {
+
+ next if (! exists($result_list{$class}));
+
+ $file = "$dir/check.dynamic.$class";
+
+ my $outfile_fh = do { local *FH; *FH };
+ if (! open($outfile_fh, ">$file")) {
+ exiter(nofile($file, $!));
+ }
+ if ($class eq 'private') {
+ print $outfile_fh
+ $text{'Message_Private_Symbols_Check_Outfile'};
+ } elsif ($class eq 'public') {
+ print $outfile_fh
+ $text{'Message_Public_Symbols_Check_Outfile'};
+ }
+ print $outfile_fh $result_list{$class};
+ close($outfile_fh);
+ }
+
+ $file = "$dir/check.problems";
+
+ if (! open($problems_fh, ">>$file")) {
+ exiter(nofile($file, $!));
+ }
+
+ if (exists($result_list{'private'})) {
+ $count = scalar(my @a = split(/\n/, $result_list{'private'}));
+ print $problems_fh "DYNAMIC: PRIVATE_SYMBOL_USE $count\n";
+ }
+ if (exists($result_list{'unbound'})) {
+ $count = scalar(@unbound_list);
+ print $problems_fh "DYNAMIC: UNBOUND_SYMBOL_USE $count\n";
+ }
+ if (exists($result_list{'unrecognized'})) {
+ $count =
+ scalar(my @a = split(/\n/, $result_list{'unrecognized'}));
+ print $problems_fh "DYNAMIC: UNRECOGNIZED_SYMBOL_USE $count\n";
+ }
+
+ close($problems_fh);
+}
+
+#
+# Loads a system model for a library on demand.
+#
+# Input is a library to load and the architecture ABI.
+#
+# On successful completion, 1 is returned and the associative array:
+#
+# %model{"$library|$abi|$symbol"} = {public,private}
+#
+# is set.
+#
+sub load_model
+{
+ #
+ # Returns 1 if the model was successfully loaded, or returns 0
+ # if it was not.
+ #
+
+ my ($library, $abi) = @_;
+
+ #
+ # This %model_loaded hash records the following states:
+ # <string> Method by which successfully loaded.
+ # __FAILED__ Failed to loaded successfully.
+ # undef Have not tried to load yet.
+ #
+ if (exists($model_loaded{"$library|$abi"})) {
+ if ($model_loaded{"$library|$abi"} eq '__FAILED__') {
+ return 0;
+ } elsif ($model_loaded{"$library|$abi"}) {
+ return 1;
+ }
+ }
+
+ my ($loaded, $ok);
+
+ $loaded = 1 if (load_model_versioned_lib($library, $abi));
+
+ # Record the result so we do not have to repeat the above:
+
+ if ($loaded) {
+ $ok = "OK";
+ my $tweaks = load_tweaks($library, $abi);
+ $ok .= ",Model_Tweaks\[$tweaks\]" if ($tweaks);
+ $model_loaded{"$library|$abi"} = $ok;
+ } else {
+ $model_loaded{"$library|$abi"} = '__FAILED__';
+ }
+
+ return $loaded;
+}
+
+#
+# Routine to load into %model any special modifications to the Solaris
+# symbol Models kept in the etc.* file.
+#
+sub load_tweaks
+{
+ my ($lib, $abi) = @_;
+
+ my $key;
+ if (exists($model_tweak{$lib}) && $model_tweak{$lib}) {
+ $key = $lib;
+ } else {
+ #
+ # check device/inode record so as to not get tricked by
+ # symlinks.
+ #
+ my ($device, $inode) = (stat($lib))[0,1];
+ if (! defined($device) || ! defined($inode)) {
+ return 0;
+ }
+ $key = "$device/$inode";
+ if (! exists($model_tweak{$key}) || ! $model_tweak{$key}) {
+ return 0;
+ }
+ #
+ # device/inode $key is recorded, so continue along
+ # using it below in the model_tweak lookup.
+ #
+ }
+
+ #
+ # etc line looks like:
+ # MODEL_TWEAK|/usr/lib/libnsl.so.1|sparc,i386|gethostname|public
+ # value looks like:
+ # gethostname|sparc,i386|public
+ #
+
+ my ($case, $abis, $sym, $class, $count);
+
+ $count = 0;
+ foreach $case (split(/,/, $model_tweak{$key})) {
+ ($sym, $abis, $class) = split(/\|/, $case);
+ if ($abis eq '*' || ($abis =~ /\b${abi}\b/)) {
+ $model{"$lib|$abi|$sym"} = $class;
+ $count++;
+ }
+ }
+
+ return $count;
+}
+
+#
+# Determine the public/private symbol model for a versioned Solaris
+# library. Returns 0 if no model could be extracted, otherwise returns a
+# string detailing the model loading.
+#
+sub load_model_versioned_lib
+{
+ my ($library, $abi) = @_;
+
+ #
+ # This subroutine runs pvs -dos directly on the Solaris shared
+ # object, and parses data that looks like this:
+ #
+ # % pvs -dos /usr/lib/libsocket.so.1
+ # ...
+ # /usr/lib/libsocket.so.1 - SUNW_1.1: __xnet_sendmsg;
+ # ...
+ # /usr/lib/libsocket.so.1 - SISCD_2.3: connect;
+ # ...
+ # /usr/lib/libsocket.so.1 - SUNWprivate_1.2: getnetmaskbyaddr;
+ #
+ # Note that data types look like:
+ # /usr/lib/libc.so.1 - SUNWprivate_1.1: __environ_lock (24);
+ #
+ # we discard the size.
+ #
+ # On successful completion 1, is returned and the hash:
+ #
+ # %model{"$library|$abi|$symbol"} = {public,private}
+ #
+ # is set.
+ #
+
+ # library must be a full path and exist:
+ if (! -f $library) {
+ return 0;
+ }
+
+ my ($rc, $output, $output_syslib);
+
+ #
+ # quote character should never happen in normal use, but if it
+ # did it will foul up the pvs commands below, so we return
+ # early.
+ #
+ if ($library =~ /'/) {
+ return 0;
+ }
+
+ #
+ # Get the entire list of symbols:
+ # note that $library does not contain a single-quote.
+ #
+ c_locale(1);
+ $output = `$cmd_pvs -dos '$library' 2>/dev/null`;
+ $rc = $?;
+ c_locale(0);
+
+ if ($rc != 0 || ($output =~ /^[\s\n]*$/)) {
+ # It is not versioned, so get out.
+ return 0;
+ }
+
+ # Library is versioned with something from this point on.
+
+ my ($line, $libtmp, $j1, $j2, $version, $symbol, $class);
+ my ($count, $public_count, $private_count);
+ my (%versions);
+ my $libbase = basename($library);
+
+ $count = 0;
+ $public_count = 0;
+ $private_count = 0;
+
+ my $is_system_lib = is_system_library($library, $abi);
+
+ my (@defs, $def);
+ if (defined($is_system_lib)) {
+ foreach $def (split(/:/, $is_system_lib)) {
+ next if ($def =~ /^FILE=/);
+ next if ($def =~ /^-$/);
+ push(@defs, $def);
+ }
+ if (@defs == 1) {
+ $is_system_lib = $defs[0];
+ }
+ }
+
+ my (@version_heads, $vers, $default_class);
+ if (defined($is_system_lib) && $is_system_lib ne 'NO_PUBLIC_SYMS') {
+ #
+ # It is a versioned system library. Extract the public
+ # symbols version head end(s)
+ #
+ if ($is_system_lib =~ /^PUBLIC=(.*)$/) {
+ @version_heads = split(/,/, $1);
+ } else {
+ push(@version_heads, $is_system_lib);
+ }
+
+ #
+ # Rerun pvs again to extract the symbols associated with
+ # the *public* inheritance chain(s).
+ #
+ c_locale(1);
+ foreach $vers (@version_heads) {
+ # something is wrong if $vers has a quote
+ $vers =~ s/'//g;
+
+ # $library has been screened for single quotes earlier.
+ $output_syslib .=
+ `$cmd_pvs -dos -N '$vers' '$library' 2>/dev/null`;
+ }
+ c_locale(0);
+ }
+
+
+ if (defined($output_syslib) && ($output_syslib !~ /^[\s\n]*$/)) {
+ #
+ # If non-empty there are some public symbols sets.
+ # First, mark everything private:
+ #
+ $output = "DEFAULT_CLASS=private\n" . $output;
+ # then overwrite the public ones:
+ $output .= "DEFAULT_CLASS=public\n" . $output_syslib;
+ } elsif (defined($is_system_lib) &&
+ $is_system_lib eq 'NO_PUBLIC_SYMS') {
+ # Everything is private:
+ $output = "DEFAULT_CLASS=private\n" . $output;
+ } else {
+ #
+ # assume public, the override will occur when version
+ # string matches /private/i. This is for 3rd party
+ # libraries.
+ #
+ $output = "DEFAULT_CLASS=public\n" . $output;
+ }
+
+ foreach $line (split(/\n/, $output)) {
+ $line = trim($line);
+ if ($line =~ /^DEFAULT_CLASS=(.*)$/) {
+ $default_class = $1;
+ next;
+ }
+ ($libtmp, $j1, $version, $symbol, $j2) = split(/\s+/, $line);
+
+ $symbol =~ s/;*$//;
+ $version =~ s/:*$//;
+
+ next if ($symbol =~ /^\s*$/);
+ next if ($version eq $libbase); # see example output above
+
+ $versions{$version}++;
+
+ $class = $default_class;
+
+ if (! $output_syslib && ($version =~ /private/i)) {
+ $class = 'private';
+ }
+
+ if ($class eq 'private') {
+ $private_count++;
+ } else {
+ if ($output_syslib) {
+ # remove the double counting of this version:
+ $versions{$version}--;
+ $private_count--;
+ $count--;
+ }
+ $public_count++;
+ }
+
+ $model{"$library|$abi|$symbol"} = $class;
+ $count++;
+ }
+
+ if (! $count) {
+ return 0;
+ }
+
+ # Construct the info string:
+ $libtmp = "load_model_versioned_lib,$library,$abi:";
+ foreach $version (sort(keys(%versions))) {
+ $libtmp .= "$version\[$versions{$version}\],";
+ }
+ $libtmp .=
+ "\[${count}symbols=${public_count}public+${private_count}private\]";
+ return $libtmp;
+}
+
+#
+# Returns a non-empty string if the $path_to_library is recognized as a
+# System (i.e. Solaris) ABI library for given abi. Returns undef
+# otherwise. The returned string will either be the public symbol version
+# name(s), "NO_PUBLIC_SYMS" if all symbols are private, or "-" if there
+# is no versioning at all.
+#
+sub is_system_library
+{
+ my ($path_to_library, $abi) = @_;
+
+ if (exists($is_system_library_cache{"$path_to_library|$abi"})) {
+ return $is_system_library_cache{"$path_to_library|$abi"};
+ }
+
+ my ($dir, $def, $key);
+
+ my ($device, $inode) = (stat($path_to_library))[0,1];
+ foreach $dir (@lib_index_loaded) {
+
+ $key = "$dir|$path_to_library|$abi";
+ $def = $lib_index_definition{$key};
+ if (defined($device) && defined($inode) && ! defined($def)) {
+ # try inode lookup (chases down unexpected symlinks)
+ $key = "$dir|$device/$inode|$abi";
+ $def = $lib_index_definition{$key};
+ }
+ last if (defined($def));
+ }
+ if (!defined($def) && $path_to_library !~ /'/) {
+ #
+ # we skip the case $path_to_library containing
+ # a single quote, so the cmd argument is protected.
+ #
+ my $tmp = `$cmd_pvs -dn '$path_to_library' 2>/dev/null`;
+ if ($tmp =~ /\b(SUNW[^;]*);/) {
+ $def = $1;
+ }
+ }
+
+ $is_system_library_cache{"$path_to_library|$abi"} = $def;
+
+ return $def;
+}
+
+#
+# Loop over each object item in the working_dir.
+# - $dir will be each one of these object directories.
+# - $path_to_object will be the corresponding actual path
+# to the the binary to be checked.
+# Output will usually be placed down in $dir, e.g. "$dir/check.foo"
+#
+sub perform_misc_checks
+{
+ my ($dir, $path_to_object);
+
+ if (! $misc_check_databases_loaded_ok) {
+ #
+ # The load was attempted in check_objects() There is no
+ # point in continuing if that loading failed.
+ #
+ return;
+ }
+
+ emsg("\n" . gettext(
+ "performing miscellaneous checks") . " ...\n\n");
+
+ while (defined($dir = next_dir_name())) {
+
+ # Map object output dir to actual path of the object:
+ $path_to_object = dir_name_to_path($dir);
+
+ if (! -f $path_to_object) {
+ exiter(nopathexist($path_to_object, $!));
+ }
+
+ # Check it:
+ misc_check($path_to_object, $dir);
+ }
+}
+
+#
+# Routine to perform the misc. checks on a given binary object. Records
+# the findings in object's output directory.
+#
+sub misc_check
+{
+ my ($path_to_object, $dir) = @_;
+
+ # Load the entire dynamic profile for this object:
+
+ my (@profile, @profile_short, %direct_syms, $file);
+ my $tmp;
+
+ $file = "$dir/profile.dynamic";
+
+ my ($app, $caller, $lib, $base, $sym);
+ my ($libsymcaller, $cnt, %sawlib);
+ if (-f $file) {
+ my $prof_fh = do { local *FH; *FH };
+ if (! open($prof_fh, "<$file")) {
+ exiter(nofile($file, $!));
+ }
+ $cnt = 0;
+ while (<$prof_fh>) {
+ next if (/^\s*#/);
+ next if (/^\s*$/);
+ chomp;
+ ($app, $caller, $lib, $sym) = split(/\|/, $_, 4);
+
+ # Skip the checking of special symbols:
+ next if (exists($skip_symbols{$sym}));
+
+ push(@profile, "$lib|$sym|$caller");
+
+ #
+ # We collect in @profile_short up to 10
+ # lib-sym-caller triples where all the libs are
+ # distinct. This is used to speed up some
+ # loops over the profile below: when we catch
+ # the lib-matching checks early in the loop we
+ # can exclude those checks from the remainder
+ # of the loop. Since a profile may involve
+ # 1000's of symbols this can be a savings.
+ #
+ if ($cnt < 10 && ! exists($sawlib{$lib})) {
+ push(@profile_short, "$lib|$sym|$caller");
+ $sawlib{$lib} = 1;
+ $cnt++;
+ }
+ }
+ close($prof_fh);
+ }
+ #
+ # Misc Check #1:
+ # Go through dynamic profile looking for scoped local symbols:
+ #
+
+ my (%all_neededs, %lib_not_found);
+ my ($scoped_list, $scoped_msg);
+ my ($sc_rel, $sc_lib, $sc_sym, $sc_val);
+
+ %all_neededs = all_ldd_neededs($path_to_object);
+ my ($key, $key_trim);
+ foreach $key (keys(%all_neededs)) {
+ $key_trim = basename($key);
+ $all_neededs{$key_trim} = $all_neededs{$key};
+ if ($all_neededs{$key} =~ /file not found/) {
+ # %lib_not_found will be used below in check #2
+ $lib_not_found{$key}++;
+ $lib_not_found{$key_trim}++;
+ }
+ }
+
+ # We will need the abi of the object:
+ my $abi;
+ ($abi) = bin_type($path_to_object);
+ if ($abi eq '' || ($abi =~ /^(unknown|any)$/)) {
+ if ($uname_p =~ /sparc/i) {
+ $abi = 'sparc';
+ } else {
+ $abi = 'i386';
+ }
+ }
+
+ foreach $libsymcaller (@profile) {
+ next unless ($libsymcaller =~ /\*DIRECT\*$/);
+
+ ($lib, $sym, $caller) = split(/\|/, $libsymcaller, 3);
+
+ #
+ # Record direct symbols to improve our %wskip list used
+ # to speed up loops over symbols.
+ #
+ $direct_syms{$sym} = 1;
+ next unless (exists($scoped_symbol_all{$sym}));
+
+ $base = basename($lib);
+
+ #
+ # We only worry if a scoped call is a direct one. This
+ # assumes the user's support shared objects are also
+ # checked by appcert.
+ #
+
+ if (exists($scoped_symbol{"$lib|$sym"}) ||
+ exists($scoped_symbol{"$base|$sym"})) {
+ #
+ # This one is for checking on releases BEFORE
+ # the scoping actually occurred.
+ #
+ $scoped_msg .= "$base:$sym ";
+ $scoped_list .= "$path_to_object|$caller|$lib|$sym\n";
+
+ } elsif ($lib eq '*UNBOUND*' &&
+ exists($scoped_symbol_all{$sym})) {
+ #
+ # This one is for checking on releases AFTER the
+ # scoping.
+ #
+ # Assume these type of unbounds are deprecated
+ # if found in scoped_symbol_all. Double check it
+ # is in the all-needed-libs though:
+ #
+
+ if (defined($sc_sym) &&
+ exists($model{"$LIBC|$abi|$sc_sym"})) {
+ next;
+ }
+
+ foreach $sc_val (split(/,/, $scoped_symbol_all{$sym})) {
+ ($sc_rel, $sc_lib, $sc_sym) =
+ split(/\|/, $sc_val);
+
+ #
+ # The general scoping that occurred for
+ # ld.so.1 makes the current heuristic
+ # somewhat less accurate. Unboundedness
+ # from other means has too good a chance
+ # of overlapping with the ld.so.1
+ # scoping. Note that the app likely does
+ # NOT have ld.so.1 in its neededs, but
+ # we still skip this case.
+ #
+
+ next if ($sc_lib eq 'ld.so.1');
+
+ if ($all_neededs{$sc_lib}) {
+ # note that $lib is '*UNBOUND*'
+ $scoped_msg .= "<unbound>:$sym ";
+ $scoped_list .=
+ "$path_to_object|$caller|$lib|$sym\n";
+ }
+ }
+ }
+ }
+
+ if (defined($scoped_msg)) {
+ my $problems = "$dir/check.problems";
+
+ # problems will be appended to the file:
+ my $problems_fh = do { local *FH; *FH };
+ if (! open($problems_fh, ">>$problems")) {
+ exiter(nofile($problems, $!));
+ }
+ print $problems_fh
+ "MISC: REMOVED_SCOPED_SYMBOLS: $scoped_msg\n";
+ close($problems_fh);
+
+ $problems = "$dir/check.demoted_symbols";
+
+ # problems will be appended to the file:
+ my $check_fh = do { local *FH; *FH };
+ if (! open($check_fh, ">>$problems")) {
+ exiter(nofile($problems, $!));
+ }
+ print $check_fh $scoped_list;
+ close($check_fh);
+ }
+
+ #
+ # Misc Check #2
+ # Go through dynamic profile looking for special warnings.
+ #
+
+ my (%warnings, %wskip);
+ my (%lib_star, %sym_star, %caller_star);
+ my ($tag, $tag0, $sub, $res);
+
+ while (($tag, $sub) = each(%warnings_match)) {
+ next if (! $sub);
+
+ $res = &{$sub}($path_to_object);
+ $warnings{$tag} = 1 if ($res);
+ }
+
+ my $warnings_bind_has_non_direct = 0;
+
+ while (($tag0, $tmp) = each(%warnings_bind)) {
+ ($lib, $sym, $caller) = split(/\|/, $tmp, 3);
+ $lib_star{$tag0} = 1 if ($lib eq '*');
+ $sym_star{$tag0} = 1 if ($sym eq '*');
+ $caller_star{$tag0} = 1 if ($caller eq '*');
+ if ($lib ne '*' && $lib !~ m,/, && ! $all_neededs{$lib}) {
+ # it can never match:
+ $wskip{$tag0} = 1;
+ }
+ if ($caller ne '*DIRECT*') {
+ # this will be used to speed up the *DIRECT* only case:
+ $warnings_bind_has_non_direct = 1;
+ } elsif ($sym ne '*' && ! $direct_syms{$sym}) {
+ # it can never match:
+ $wskip{$tag0} = 1;
+ }
+ }
+
+ foreach $lib (keys(%lib_not_found)) {
+ #
+ # add a placeholder symbol in %profile to indicate
+ # $lib is on dtneeded, but wasn't found. This will
+ # match a $sym = '*' warnings_bind misc check:
+ #
+ push(@profile,
+ "$lib|__ldd_indicated_file_not_found__|*DIRECT*");
+ }
+
+ my ($l_t, $s_t, $c_t, $match_t);
+
+ my (@tag_list, @tag_list2, $new_tags);
+ #
+ # create a list of tags excluding the ones we know will be
+ # skipped in the $libsymcaller loop below.
+ #
+ foreach $tag0 (keys(%warnings_bind)) {
+ next if ($wskip{$tag0});
+ push(@tag_list, $tag0);
+ }
+
+ #
+ # we loop over @profile_short first, these will give us up to
+ # 10 different libraries early to help us shrink @tag_list
+ # as we go through the profile.
+ #
+ foreach $libsymcaller (@profile_short, @profile) {
+ @tag_list = @tag_list2 if ($new_tags);
+ last if (! @tag_list);
+
+ ($lib, $sym, $caller) = split(/\|/, $libsymcaller, 3);
+
+ if (! $warnings_bind_has_non_direct && $caller ne '*DIRECT*') {
+ next;
+ }
+
+ $base = basename($lib);
+ $new_tags = 0;
+
+ foreach $tag0 (@tag_list) {
+
+ # try to get out early:
+ next if ($wskip{$tag0});
+
+ ($tag, $tmp) = split(/\|/, $tag0, 2);
+ # try to get out early:
+ next if ($warnings{$tag});
+
+ $match_t = $warnings_bind{$tag0};
+
+ $l_t = $lib;
+ $s_t = $sym;
+ $c_t = $caller;
+
+ $l_t = '*' if ($lib_star{$tag0});
+ $s_t = '*' if ($sym_star{$tag0});
+ $c_t = '*' if ($caller_star{$tag0});
+
+ if ("$l_t|$s_t|$c_t" eq $match_t ||
+ "$base|$s_t|$c_t" eq $match_t) {
+ $warnings{$tag} = 1;
+ $wskip{$tag0} = 1;
+
+ # shorten tag list:
+ my (@t, $tg, $tg2, $tp);
+ foreach $tg (@tag_list) {
+ next if ($tg eq $tag0);
+ ($tg2, $tp) = split(/\|/, $tg, 2);
+ next if ($tg2 eq $tag);
+ push(@t, $tg);
+ }
+ @tag_list2 = @t;
+ $new_tags = 1;
+ }
+ }
+ }
+
+ if (%warnings) {
+ my $problems = "$dir/check.problems";
+
+ # append problems to the file:
+ my $problems_fh = do { local *FH; *FH };
+ if (! open($problems_fh, ">>$problems")) {
+ exiter(nofile($problems, $!));
+ }
+
+ my $tag;
+ foreach $tag (keys(%warnings)) {
+ print $problems_fh "MISC: WARNING: $tag\n";
+ }
+ close($problems_fh);
+ }
+}
diff --git a/usr/src/cmd/abi/appcert/scripts/symprof.pl b/usr/src/cmd/abi/appcert/scripts/symprof.pl
new file mode 100644
index 0000000..ce16962
--- /dev/null
+++ b/usr/src/cmd/abi/appcert/scripts/symprof.pl
@@ -0,0 +1,1646 @@
+#!/usr/perl5/bin/perl -w
+#
+# 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
+#
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This utility program creates the profiles of the binaries to be
+# checked.
+#
+# The dynamic profiling is done by running ldd -r on the binary with
+# LD_DEBUG=files,bindings and parsing the linker debug output.
+#
+# The static profiling (gathering of .text symbols) is done by calling
+# the utility program static_prof.
+#
+
+require 5.005;
+use strict;
+use locale;
+use POSIX qw(locale_h);
+use Sun::Solaris::Utils qw(textdomain gettext);
+use File::Basename;
+use File::Path;
+
+use lib qw(/usr/lib/abi/appcert);
+use AppcertUtil;
+
+setlocale(LC_ALL, "");
+textdomain(TEXT_DOMAIN);
+
+use vars qw(
+ $tmp_prof_dir
+);
+
+set_clean_up_exit_routine(\&clean_up_exit);
+
+import_vars_from_environment();
+
+signals('on', \&interrupted);
+
+set_working_dir();
+
+profile_objects();
+
+clean_up();
+
+exit 0;
+
+#
+# working_dir has been imported by import_vars_from_environment() from
+# appcert. A sanity check is performed here to make sure it exists.
+#
+sub set_working_dir
+{
+ if (! defined($working_dir) || ! -d $working_dir) {
+ exiter("$command_name: " . sprintf(gettext(
+ "cannot locate working directory: %s\n"), $working_dir));
+ }
+}
+
+#
+# Routine called when interrupted by user (e.g. SIGINT).
+#
+sub interrupted
+{
+ $SIG{$_[0]} = 'DEFAULT';
+ signals('off');
+ clean_up_exit(1);
+}
+
+#
+# Does the cleanup then exits with return code $rc. Note: The utility
+# routine exiter() calls this routine.
+#
+sub clean_up_exit
+{
+ my ($rc) = @_;
+ $rc = 0 unless ($rc);
+
+ clean_up();
+ exit $rc;
+}
+
+#
+# General cleanup activities.
+#
+sub clean_up
+{
+ if (defined($tmp_prof_dir) && -d $tmp_prof_dir) {
+ rmtree($tmp_prof_dir);
+ }
+}
+
+#
+# Top level routine to loop over the objects and call the profiling
+# routines on each.
+#
+sub profile_objects
+{
+ # Make a tmp directory for the profiling work.
+ $tmp_prof_dir = create_tmp_dir($tmp_dir);
+
+ if (! -d $tmp_prof_dir) {
+ exiter(nocreatedir($tmp_prof_dir, $!));
+ }
+
+ my ($dir, $path_to_object);
+
+ #
+ # Loop over each object item in the working_dir.
+ # - $dir will be each one of these object directories.
+ # - $path_to_object will be the corresponding actual path
+ # to the the binary to be profiled.
+ # Output will usually be placed down in $dir, e.g. "$dir/profile.static"
+ #
+
+ my $cnt = -1;
+ my $last_i;
+ while (defined($dir = next_dir_name())) {
+ $cnt++;
+ if ($block_max ne '') {
+ next if ($cnt < $block_min || $cnt >= $block_max);
+ }
+
+ $last_i = $cnt;
+
+ # Map object output directory to actual path of the object:
+ $path_to_object = dir_name_to_path($dir);
+
+ if (! -f $path_to_object) {
+ exiter(nopathexist($path_to_object, $!));
+ }
+
+ # Profile it:
+
+ emsg(gettext("profiling: %s\n"), $path_to_object);
+
+ static_profile($path_to_object, $dir);
+
+ dynamic_profile($path_to_object, $dir);
+ }
+
+ # Only try this after everything has been initially profiled.
+ if (! $block_max || $last_i >= $binary_count - 1) {
+ redo_unbound_profile();
+ }
+ clean_up(); # Remove any tmp dirs and files.
+}
+
+#
+# Runs utility program static_prof on the object and places results in
+# output directory.
+#
+sub static_profile($$)
+{
+ my ($object, $output_dir) = @_;
+
+ # This is the location of static_prof's output file:
+
+ my $outfile = "$output_dir/profile.static";
+
+ # It is consumed by static_check_object() in symcheck.
+
+ #
+ # Do not run on *completely* statically linked objects. This
+ # case will be caught and noted in the dynamic profiling and
+ # checking.
+ #
+ my $skip_it;
+ if (is_statically_linked($object)) {
+ $skip_it = "STATICALLY_LINKED";
+ } elsif (! is_elf($object)) {
+ $skip_it = "NON_ELF";
+ }
+
+ my $static_prof_fh = do { local *FH; *FH };
+ if (defined($skip_it)) {
+ open($static_prof_fh, ">$outfile") ||
+ exiter(nofile($outfile, $!));
+
+ print $static_prof_fh "#SKIPPED_TEST: $skip_it\n";
+ close($static_prof_fh);
+
+ return;
+ }
+
+ #
+ # system() when run in the following manner will prevent the
+ # shell from expanding any strange characters in $object. Quotes
+ # around '$object' would be almost as safe. since excluded
+ # earlier the cases where it contains the ' character.
+ #
+ system("$appcert_lib_dir/static_prof", '-p', '-s', '-o', $outfile,
+ $object);
+
+ if ($? != 0) {
+ open($static_prof_fh, ">$outfile") ||
+ exiter(nofile($outfile, $!));
+
+ #
+ # For completeness, we'll use elfdump to record the
+ # static profile for 64 bit binaries, although the
+ # static linking problems only occur for 32-bit
+ # applications.
+ #
+ my ($prof, $sym);
+ $prof = '';
+ my $elfdump_fh = do { local *FH; *FH };
+ if (open($elfdump_fh, "$cmd_elfdump -s -N .dynsym '$object' " .
+ " 2>/dev/null |")) {
+ while (<$elfdump_fh>) {
+ chomp;
+ if (/\s\.text\s+(\S+)$/) {
+ $sym = $1;
+ if (! /\bFUNC\b/) {
+ next;
+ }
+ if (/\bGLOB\b/) {
+ $prof .= "$object|TEXT|GLOB|" .
+ "FUNC|$sym\n";
+ } else {
+ $prof .= "$object|TEXT|WEAK|" .
+ "FUNC|$sym\n";
+ }
+ }
+ }
+ close($elfdump_fh);
+ }
+ if ($prof ne '') {
+ my $line;
+ print $static_prof_fh "#generated by symprof/elfdump\n";
+ print $static_prof_fh "#dtneeded:";
+ foreach $line (split(/\n/, cmd_output_dump($object))) {
+ if ($line =~ /\bNEEDED\s+(\S+)/) {
+ print $static_prof_fh " $1";
+ }
+ }
+ print $static_prof_fh "\n";
+ print $static_prof_fh $prof;
+ } else {
+ print $static_prof_fh "#SKIPPED_TEST: " .
+ "PROFILER_PROGRAM_static_prof_RETURNED:$?\n";
+ }
+ close($static_prof_fh);
+
+
+ return;
+ }
+
+ # Also store the dtneededs from the static profile output.
+ my $dtneeded = "$output_dir/info.dtneeded";
+
+ my $dtneeded_fh = do { local *FH; *FH };
+ open($dtneeded_fh, ">$dtneeded") ||
+ exiter(nofile($dtneeded, $!));
+
+ open($static_prof_fh, "<$outfile") ||
+ exiter(nofile($outfile, $!));
+
+ my $lib;
+ while (<$static_prof_fh>) {
+
+ next unless (/^\s*#/);
+
+ if (/^\s*#\s*dtneeded:\s*(\S.*)$/) {
+ foreach $lib (split(/\s+/, $1)) {
+ next if ($lib eq '');
+ print $dtneeded_fh "$lib\n";
+ }
+ last;
+ }
+ }
+ close($dtneeded_fh);
+ close($static_prof_fh);
+}
+
+#
+# Top level subroutine for doing a dynamic profile of an object. It
+# calls get_dynamic_profile() which handles the details of the actual
+# profiling and returns the newline separated "preprocessed format" to
+# this subroutine.
+#
+# The records are then processed and placed in the output directory.
+#
+sub dynamic_profile
+{
+ my ($object, $output_dir) = @_;
+
+ my ($profile, $line, $tmp);
+
+ # This is the profile output file.
+ my $outfile = "$output_dir/profile.dynamic";
+
+ $profile = get_dynamic_profile($object);
+
+ if ($profile =~ /^ERROR:\s*(.*)$/) {
+ # There was some problem obtaining the dynamic profile
+ my $msg = $1;
+ my $errfile = "$output_dir/profile.dynamic.errors";
+
+ my $profile_error_fh = do { local *FH; *FH };
+ open($profile_error_fh, ">>$errfile") ||
+ exiter(nofile($errfile, $!));
+
+ $msg =~ s/\n/ /g;
+ $msg =~ s/;/,/g;
+ print $profile_error_fh $msg, "\n";
+ close($profile_error_fh);
+
+ # Write a comment to the profile file as well:
+ my $profile_fh = do { local *FH; *FH };
+ open($profile_fh, ">$outfile") ||
+ exiter(nofile($outfile, $!));
+ print $profile_fh "#NO_BINDINGS_FOUND $msg\n";
+ close($profile_fh);
+
+ return;
+ }
+
+ my ($filter, $filtee, $from, $to, $sym);
+ my ($type, $saw_bindings, $all_needed);
+ my (%filter_map, %symlink_map);
+
+ # Resolve the symlink of the object, if any.
+ $symlink_map{$object} = follow_symlink($object);
+
+ #
+ # Collect the filter or static linking info first. Since the
+ # filter info may be used to alias libraries, it is safest to do
+ # it before any bindings processing. that is why we iterate
+ # through $profile twice.
+ #
+ my @dynamic_profile_array = split(/\n/, $profile);
+
+ foreach $line (@dynamic_profile_array) {
+
+ if ($line =~ /^FILTER_AUX:(.*)$/) {
+ #
+ # Here is the basic example of an auxiliary filter:
+ #
+ # FILTER: /usr/lib/libc.so.1
+ # FILTEE: /usr/platform/sun4u/lib/libc_psr.so.1
+ #
+ # The app links against symbol memcpy() in
+ # libc.so.1 at build time. Now, at run time IF
+ # memcpy() is provided by libc_psr.so.1 then
+ # that "code" is used, otherwise it backs off to
+ # use the memcpy()in libc.so.1. The
+ # libc_psr.so.1 doesn't even have to exist.
+ #
+ # The dynamic linker happily informs us that it
+ # has found (and will bind to) memcpy() in
+ # /usr/platform/sun4u/lib/libc_psr.so.1. We
+ # want to alias libc_psr.so.1 => libc.so.1.
+ # Why?
+ # - less models to maintain. Note the symlink
+ # situation in /usr/platform.
+ # - libc_psr.so.1 is versioned, but we would be
+ # incorrect since it has memcpy() as SUNWprivate
+ #
+ # Therefore we record this aliasing in the hash
+ # %filter_map. This will be used below to
+ # replace occurrences of the FILTEE string by
+ # the FILTER string. Never the other way round.
+ #
+
+ ($filter, $filtee) = split(/\|/, $1, 2);
+ $filter_map{$filtee} = $filter;
+
+ # Map the basenames too:
+ $filter = basename($filter);
+ $filtee = basename($filtee);
+ $filter_map{$filtee} = $filter;
+
+ } elsif ($line =~ /^FILTER_STD:(.*)$/) {
+
+ #
+ # Here is the basic example(s) of a standard filter:
+ #
+ # FILTER: /usr/lib/libsys.so.1
+ # FILTEE: /usr/lib/libc.so.1
+ #
+ # Here is another:
+ #
+ # FILTER: /usr/lib/libw.so.1
+ # FILTEE: /usr/lib/libc.so.1
+ #
+ # Here is a more perverse one, libxnet.so.1 has 3
+ # filtees:
+ #
+ # FILTER: /usr/lib/libxnet.so.1
+ # FILTEE: /usr/lib/{libsocket.so.1,libnsl.so.1,libc.so.1}
+ #
+ # The important point to note about standard
+ # filters is that they contain NO CODE AT ALL.
+ # All of the symbols in the filter MUST be found
+ # in (and bound to) the filtee(s) or there is a
+ # relocation error.
+ #
+ # The app links against symbol getwc() in
+ # libw.so.1 at build time. Now, at run time
+ # getwc() is actually provided by libc.so.1.
+ #
+ # The dynamic linker happily informs us that it
+ # has found (and will bind to) getwc() in
+ # libc.so.1. IT NEVER DIRECTLY TELLS US getwc was
+ # actually referred to in libw.so.1
+ #
+ # So, unless we open a model file while
+ # PROFILING, we cannot figure out which ones
+ # come from libw.so.1 and which ones come from
+ # libc.so.1. In one sense this is too bad: the
+ # libw.so.1 structure is lost.
+ #
+ # The bottom line is we should not alias
+ # libc.so.1 => libw.so.1 (FILTEE => FILTER) as
+ # we did above with FILTER_AUX. That would be a
+ # disaster. (would say EVERYTHING in libc came
+ # from libw!)
+ #
+ # So we DO NOT store the alias in this case, this
+ # leads to:
+ # - more models to maintain.
+ #
+ # Thus we basically skip this info.
+ # EXCEPT for one case, libdl.so.1, see below.
+ #
+
+ ($filter, $filtee) = split(/\|/, $1, 2);
+
+ #
+ # The dlopen(), ... family of functions in
+ # libdl.so.1 is implemented as a filter for
+ # ld.so.1. We DO NOT want to consider a symbol
+ # model for ld.so.1. So in this case alone we
+ # want to alias ld.so.1 => libdl.so.1
+ #
+ #
+ # We only need to substitute the standard filter
+ # libdl.so.n. Record the alias in that case.
+ #
+ if ($filter =~ /\blibdl\.so\.\d+/) {
+ $filter_map{$filtee} = $filter;
+
+ # Map basenames too:
+ $filter = basename($filter);
+ $filtee = basename($filtee);
+ $filter_map{$filtee} = $filter;
+ }
+
+ } elsif ($line =~ /^DYNAMIC_PROFILE_SKIPPED_NOT_ELF/ ||
+ $line =~ /^STATICALLY_LINKED:/) {
+ #
+ # This info will go as a COMMENT into the
+ # output. n.b.: there is no checking whether
+ # this piece of info is consistent with the rest
+ # of the profile output.
+ #
+ # The $message string will come right after the
+ # header, and before the bindings (if any). See
+ # below where we write to the PROF filehandle.
+ #
+
+ my $profile_msg_fh = do { local *FH; *FH };
+ open($profile_msg_fh, ">>$outfile") ||
+ exiter(nofile($outfile, $!));
+ print $profile_msg_fh "#$line\n";
+ close($profile_msg_fh);
+
+ } elsif ($line =~ /^NEEDED_FOUND:(.*)$/) {
+ #
+ # These libraries are basically information
+ # contained in the ldd "libfoo.so.1 =>
+ # /usr/lib/libfoo.so.1" output lines. It is the
+ # closure of the neededs (not just the directly
+ # needed ones).
+ #
+
+ $all_needed .= $1 . "\n";
+ }
+ }
+
+ #
+ # Now collect the bindings info:
+ #
+ # Each BINDING record refers to 1 symbol. After manipulation
+ # here it will go into 1 record into the profile output.
+ #
+ # What sort of manipulations? Looking below reveals:
+ #
+ # - we apply the library FILTER_AUX aliases in %filter_map
+ # - for shared objects we resolve symbolic links to the actual
+ # files they point to.
+ # - we may be in a mode where we do not store full paths of
+ # the shared objects, e.g. /usr/lib/libc.so.1, but rather
+ # just their basename "libc.so.1"
+ #
+ # There are exactly four(4) types of bindings that will be
+ # returned to us by get_dynamic_profile(). See
+ # get_dynamic_profile() and Get_ldd_Profile() for more details.
+ #
+ # Here are the 4 types:
+ #
+ # BINDING_DIRECT:from|to|sym
+ # The object being profiled is the "from" here!
+ # It directly calls "sym" in library "to".
+ #
+ # BINDING_INDIRECT:from|to|sym
+ # The object being profiled is NOT the "from" here.
+ # "from" is a shared object, and "from" calls "sym" in
+ # library "to".
+ #
+ # BINDING_REVERSE:from|to|sym
+ # The shared object "from" makes a reverse binding
+ # all the way back to the object being profiled! We call
+ # this *REVERSE*. "to" is the object being profiled.
+ #
+ # BINDING_UNBOUND:from|sym
+ # object "from" wants to call "sym", but "sym" was
+ # not found! We didn't find the "to", and so no
+ # "to" is passed to us.
+ #
+
+ my $put_DIRECT_in_the_UNBOUND_record;
+
+ $saw_bindings = 0;
+ #
+ # Start the sorting pipeline that appends to the output file.
+ # It will be written to in the following loop.
+ #
+ # Tracing back $outfile to $outdir to $working_dir, one sees $outfile
+ # should have no single-quote characters. We double check it does not
+ # before running the command.
+ #
+ if ($outfile =~ /'/) {
+ exiter(norunprog("|$cmd_sort -t'|' +1 | $cmd_uniq >> '$outfile'"));
+ }
+
+ my $prof_fh = do { local *FH; *FH };
+ open($prof_fh, "|$cmd_sort -t'|' +1 | $cmd_uniq >> '$outfile'") ||
+ exiter(norunprog("|$cmd_sort -t'|' +1 | $cmd_uniq >> '$outfile'",
+ $!));
+ local($SIG{'PIPE'}) = sub {
+ exiter(norunprog(
+ "|$cmd_sort -t'|' +1 | $cmd_uniq >> '$outfile'", $!));
+ };
+
+ foreach $line (@dynamic_profile_array) {
+
+ if ($line =~ /^BINDING_([^:]+):(.*)$/) {
+
+ $type = $1;
+
+ if ($type eq 'UNBOUND') {
+ #
+ # If the symbol was unbound, there is no
+ # "to" library. We make an empty "to"
+ # value so as to avoid special casing
+ # "to" all through the code that
+ # follows. It is easy to verify no
+ # matter what happens with the $to
+ # variable, it will NOT be printed to the
+ # profile output file in the UNBOUND
+ # case.
+ #
+
+ ($from, $sym) = split(/\|/, $2, 2);
+ $to = '';
+
+ } else {
+ # Otherwise, we have the full triple:
+
+ ($from, $to, $sym) = split(/\|/, $2, 3);
+ }
+
+ #
+ # We record here information to be used in
+ # writing out UNBOUND records, namely if the
+ # "from" happened to also be the object being
+ # profiled. In that case The string "*DIRECT*"
+ # will be placed in the "*UNBOUND*" record,
+ # otherwise the "from" will stand as is in the
+ # "*UNBOUND*" record. We do this check here
+ # before the filter_map is applied. The chances
+ # of it making a difference is small, but we had
+ # best to do it here.
+ #
+ if (files_equal($from, $object)) {
+ #
+ # Switch to indicate placing *DIRECT* in
+ # the *UNBOUND* line, etc.
+ #
+ $put_DIRECT_in_the_UNBOUND_record = 1;
+ } else {
+ $put_DIRECT_in_the_UNBOUND_record = 0;
+ }
+
+ #
+ # See if there is a filter name that "aliases"
+ # either of the "from" or "to" libraries, if so
+ # then rename it.
+ #
+ if ($to ne '' && $filter_map{$to}) {
+ $to = $filter_map{$to};
+ }
+ if ($type ne 'DIRECT' && $filter_map{$from}) {
+ $from = $filter_map{$from};
+ }
+
+ #
+ # Record symlink information.
+ #
+ # Note that follow_symlink returns the file
+ # name itself when the file is not a symlink.
+ #
+ # Work out if either "from" or "to" are
+ # symlinks. For efficiency we keep them in the
+ # %symlink_map hash. Recall that we are in a
+ # loop here, so why do libc.so.1 200 times?
+ #
+ if ($from ne '') {
+ if (! exists($symlink_map{$from})) {
+ $symlink_map{$from} =
+ follow_symlink($from);
+ }
+ }
+ if ($to ne '') {
+ if (! exists($symlink_map{$to})) {
+ $symlink_map{$to} =
+ follow_symlink($to);
+ }
+ }
+
+ #
+ # Now make the actual profile output line. Construct
+ # it in $tmp and then append it to $prof_fh pipeline.
+ #
+ $tmp = '';
+
+ if ($type eq "DIRECT") {
+ $tmp = "$object|*DIRECT*|$to|$sym";
+ } elsif ($type eq "INDIRECT") {
+ $tmp = "$object|$from|$to|$sym";
+ } elsif ($type eq "REVERSE") {
+ $tmp = "$object|*REVERSE*|$from|$sym";
+ } elsif ($type eq "UNBOUND") {
+ if ($put_DIRECT_in_the_UNBOUND_record) {
+ $tmp =
+ "$object|*DIRECT*|*UNBOUND*|$sym";
+ } else {
+ $tmp = "$object|$from|*UNBOUND*|$sym";
+ }
+ } else {
+ exiter("$command_name: " . sprintf(gettext(
+ "unrecognized ldd(1) LD_DEBUG " .
+ "bindings line: %s\n"), $line));
+ }
+
+ # write it to the sorting pipeline:
+ print $prof_fh $tmp, "\n";
+ $saw_bindings = 1;
+ } elsif ($line =~ /^DYNAMIC_PROFILE_SKIPPED_NOT_ELF/) {
+ # ignore no bindings warning for non-ELF
+ $saw_bindings = 1;
+ }
+ }
+
+ if (! $saw_bindings) {
+ print $prof_fh "#NO_BINDINGS_FOUND\n";
+ }
+ close($prof_fh);
+ if ($? != 0) {
+ exiter(norunprog(
+ "|$cmd_sort -t'|' +1 | $cmd_uniq >> '$outfile'", $!));
+ }
+
+ # Print out the library location and symlink info.
+ $outfile = "$output_dir/profile.dynamic.objects";
+
+ my $objects_fh = do { local *FH; *FH };
+ open($objects_fh, ">$outfile") || exiter(nofile($outfile, $!));
+
+ my ($var, $val);
+ while (($var, $val) = each(%ENV)) {
+ if ($var =~ /^LD_/) {
+ print $objects_fh "#info: $var=$val\n";
+ }
+ }
+
+ my $obj;
+ foreach $obj (sort(keys(%symlink_map))) {
+ next if ($obj eq '');
+ print $objects_fh "$obj => $symlink_map{$obj}\n";
+ }
+ close($objects_fh);
+
+ # Print out ldd shared object resolution.
+ $outfile = "$output_dir/profile.dynamic.ldd";
+
+ my $ldd_prof_fh = do { local *FH; *FH };
+ open($ldd_prof_fh, ">$outfile") || exiter(nofile($outfile, $!));
+
+ if (defined($all_needed)) {
+ print $ldd_prof_fh $all_needed;
+ }
+ close($ldd_prof_fh);
+
+}
+
+#
+# If the users environment is not the same when running symprof as when
+# running their application, the dynamic linker cannot resolve all of
+# the dynamic bindings and we get "unbound symbols".
+# redo_unbound_profile attempts to alleviate this somewhat. In
+# particular, for shared objects that do not have all of their
+# dependencies recorded, it attempts to use binding information in the
+# other *executables* under test to supplement the binding information
+# for the shared object with unbound symbols. This is not the whole
+# story (e.g. dlopen(3L)), but it often helps considerably.
+#
+sub redo_unbound_profile
+{
+ my ($dir, $path_to_object);
+ my ($profile, $total, $count);
+ my (%unbound_bins);
+
+ #
+ # Find the objects with unbound symbols. Put them in the list
+ # %unbound_bins.
+ #
+ $total = 0;
+ while (defined($dir = next_dir_name())) {
+
+ $profile = "$dir/profile.dynamic";
+ my $profile_fh = do { local *FH; *FH };
+ if (! -f $profile || ! open($profile_fh, "<$profile")) {
+ next;
+ }
+
+ $count = 0;
+ while (<$profile_fh>) {
+ next if (/^\s*#/);
+ $count++ if (/\|\*UNBOUND\*\|/);
+ }
+ close($profile_fh);
+
+ $unbound_bins{$dir} = $count if ($count);
+ $total += $count;
+ }
+
+ # we are done if no unbounds are detected.
+ return unless (%unbound_bins);
+ return if ($total == 0);
+
+ my (%dtneededs_lookup_full, %dtneededs_lookup_base);
+
+ # Read in *ALL* objects dt_neededs.
+
+ my ($soname, $base, $full);
+ while (defined($dir = next_dir_name())) {
+
+ $profile = "$dir/profile.dynamic.ldd";
+ my $all_neededs_fh = do { local *FH; *FH };
+ if (! open($all_neededs_fh, "<$profile")) {
+ # this is a heuristic, so we skip on to the next
+ next;
+ }
+
+ while (<$all_neededs_fh>) {
+ chop;
+ next if (/^\s*#/);
+ # save the dtneeded info:
+ ($soname, $full) = split(/\s+=>\s+/, $_);
+
+ if ($full !~ /not found|\)/) {
+ $dtneededs_lookup_full{$full}{$dir} = 1;
+ }
+ if ($soname !~ /not found|\)/) {
+ $base = basename($soname);
+ $dtneededs_lookup_base{$base}{$dir} = 1;
+ }
+ }
+ close($all_neededs_fh);
+ }
+
+ emsg("\n" . gettext(
+ "re-profiling binary objects with unbound symbols") . " ...\n");
+
+ # Now combine the above info with each object having unbounds:
+
+ my $uref = \%unbound_bins;
+ foreach $dir (keys(%unbound_bins)) {
+
+ # Map object output directory to the actual path of the object:
+ $path_to_object = dir_name_to_path($dir);
+
+ #
+ # Here is the algorithm:
+ #
+ # 1) binary with unbounds must be a shared object.
+ #
+ # 2) check if it is in the dtneeded of other product binaries.
+ # if so, use the dynamic profile of those binaries
+ # to augment the bindings of the binary with unbounds
+ #
+
+ if (! -f $path_to_object) {
+ exiter(nopathexist($path_to_object, $!));
+ }
+
+ # only consider shared objects (e.g. with no DTNEEDED recorded)
+ if (! is_shared_object($path_to_object)) {
+ next;
+ }
+
+ $base = basename($path_to_object);
+
+ my (@dirlist);
+
+ my $result = 0;
+
+ if (defined($dtneededs_lookup_base{$base})) {
+ # the basename is on another's dtneededs:
+ @dirlist = keys(%{$dtneededs_lookup_base{$base}});
+ # try using the bindings of these executables:
+ $result =
+ try_executables_bindings($dir, $uref, @dirlist);
+ }
+ if ($result) {
+ # we achieved some improvements and so are done:
+ next;
+ }
+
+ # Otherwise, try objects that have our full path in their
+ # dtneededs:
+ @dirlist = ();
+ foreach $full (keys(%dtneededs_lookup_full)) {
+ if (! files_equal($path_to_object, $full)) {
+ next;
+ }
+ push(@dirlist, keys(%{$dtneededs_lookup_full{$full}}));
+ }
+ if (@dirlist) {
+ $result =
+ try_executables_bindings($dir, $uref, @dirlist);
+ }
+ }
+ emsg("\n");
+}
+
+#
+# We are trying to reduce unbound symbols of shared objects/libraries
+# under test that *have not* recorded their dependencies (i.e.
+# DTNEEDED's). So we look for Executables being checked that have *this*
+# binary ($path_to_object, a shared object) on *its* DTNEEDED. If we
+# find one, we use those bindings.
+#
+sub try_executables_bindings
+{
+ my ($dir, $uref, @dirlist) = @_;
+
+ my $path_to_object = dir_name_to_path($dir);
+
+ #
+ # N.B. The word "try" here means for a binary (a shared library,
+ # actually) that had unbound symbols, "try" to use OTHER
+ # executables binding info to resolve those unbound symbols.
+ #
+ # At least one executable needs this library; we select the one
+ # with minimal number of its own unbounds.
+ #
+ my (%sorting_list);
+ my (@executables_to_try);
+ my ($dir2, $cnt);
+ foreach $dir2 (@dirlist) {
+ next if (! defined($dir2));
+ next if ($dir2 eq $dir);
+ if (exists($uref->{$dir2})) {
+ $cnt = $uref->{$dir2};
+ } else {
+ #
+ # This binary is not on the unbounds list, so
+ # give it the highest priority.
+ #
+ $cnt = 0;
+ }
+ $sorting_list{"$dir2 $cnt"} = $dir2;
+ }
+
+ foreach my $key (reverse(sort_on_count(keys %sorting_list))) {
+ push(@executables_to_try, $sorting_list{$key});
+ }
+
+ my ($my_new_count, $my_new_profile, %my_new_symbols);
+ my ($object, $caller, $callee, $sym, $profile);
+ my $reprofiled = 0;
+
+ my ($line, $path2);
+
+ foreach $dir2 (@executables_to_try) {
+ $path2 = dir_name_to_path($dir2);
+ emsg(gettext(
+ "re-profiling: %s\n" .
+ "using: %s\n"), $path_to_object, $path2);
+
+ # read the other binary's profile
+
+ $profile = "$dir2/profile.dynamic";
+ if (! -f $profile) {
+ next;
+ }
+
+ my $prof_try_fh = do { local *FH; *FH };
+ open($prof_try_fh, "<$profile") ||
+ exiter(nofile($profile, $!));
+
+ # initialize for the next try:
+ $my_new_profile = '';
+ $my_new_count = 0;
+ %my_new_symbols = ();
+
+ # try to find bindings that involve us ($dir)
+ while (<$prof_try_fh>) {
+ chop($line = $_);
+ next if (/^\s*#/);
+ next if (/^\s*$/);
+ ($object, $caller, $callee, $sym) =
+ split(/\|/, $line, 4);
+
+ if ($caller eq '*REVERSE*') {
+ next if ($callee =~ /^\*.*\*$/);
+ if (! files_equal($callee, $path_to_object)) {
+ next;
+ }
+
+ $my_new_profile .=
+ "$callee|*DIRECT*|REVERSE_TO:" .
+ "$object|$sym\n";
+
+ $my_new_symbols{$sym}++;
+ $my_new_count++;
+
+ } elsif (files_equal($caller, $path_to_object)) {
+ $my_new_profile .=
+ "$caller|*DIRECT*|$callee|$sym\n";
+
+ $my_new_symbols{$sym}++;
+ $my_new_count++;
+ }
+ }
+ close($prof_try_fh);
+
+ next if (! $my_new_count);
+
+ # modify our profile with the new information:
+ $profile = "$dir/profile.dynamic";
+ if (! rename($profile, "$profile.0") || ! -f "$profile.0") {
+ return 0;
+ }
+ my $prof_orig_fh = do { local *FH; *FH };
+ if (! open($prof_orig_fh, "<$profile.0")) {
+ rename("$profile.0", $profile);
+ return 0;
+ }
+ my $prof_fh = do { local *FH; *FH };
+ if (! open($prof_fh, ">$profile")) {
+ rename("$profile.0", $profile);
+ return 0;
+ }
+ my $resolved_from = dir_name_to_path($dir2);
+ print $prof_fh "# REDUCING_UNBOUNDS_VIA_PROFILE_FROM: " .
+ "$resolved_from\n";
+
+ while (<$prof_orig_fh>) {
+ if (/^\s*#/) {
+ print $prof_fh $_;
+ next;
+ }
+ chop($line = $_);
+ ($object, $caller, $callee, $sym) =
+ split(/\|/, $line, 4);
+ if (! exists($my_new_symbols{$sym})) {
+ print $prof_fh $_;
+ next;
+ }
+ print $prof_fh "# RESOLVED_FROM=$resolved_from: $_";
+ }
+ close($prof_orig_fh);
+ print $prof_fh "# NEW_PROFILE:\n" . $my_new_profile;
+ close($prof_fh);
+
+ $reprofiled = 1;
+ last;
+ }
+ return $reprofiled;
+}
+
+#
+# This routine calls get_ldd_output on the object and parses the
+# LD_DEBUG output. Returns a string containing the information in
+# standard form.
+#
+sub get_dynamic_profile
+{
+ my ($object) = @_;
+
+ # Check if the object is statically linked:
+
+ my $str;
+ if (! is_elf($object)) {
+ return "DYNAMIC_PROFILE_SKIPPED_NOT_ELF";
+ } elsif (is_statically_linked($object)) {
+ $str = cmd_output_file($object);
+ return "STATICALLY_LINKED: $str";
+ }
+
+ # Get the raw ldd output:
+ my $ldd_output = get_ldd_output($object);
+
+ if ($ldd_output =~ /^ERROR:/) {
+ # some problem occurred, pass the error upward:
+ return $ldd_output;
+ }
+
+ # variables for manipulating the output:
+ my ($line, $filters, $neededs, $rest);
+ my ($tmp, $tmp2, @bindings);
+
+ # Now parse it:
+
+ foreach $line (split(/\n/, $ldd_output)) {
+
+ if ($line =~ /^\d+:\s*(.*)$/) {
+ # LD_DEBUG profile line, starts with "NNNNN:"
+ $tmp = $1;
+ next if ($tmp eq '');
+
+ if ($tmp =~ /^binding (.*)$/) {
+ #
+ # First look for:
+ # binding file=/bin/pagesize to \
+ # file=/usr/lib/libc.so.1: symbol `exit'
+ #
+ $tmp = $1;
+ push(@bindings, ldd_binding_line($1, $object));
+
+ } elsif ($tmp =~ /^file=\S+\s+(.*)$/) {
+ #
+ # Next look for:
+ # file=/usr/platform/SUNW,Ultra-1/\
+ # lib/libc_psr.so.1; filtered by /usr...
+ # file=libdl.so.1; needed by /usr/lib/libc.so.1
+ #
+ $rest = trim($1);
+
+ if ($rest =~ /^filtered by /) {
+ $filters .=
+ ldd_filter_line($tmp);
+ } elsif ($rest =~ /^needed by /) {
+ $neededs .=
+ ldd_needed_line($tmp, $object);
+ }
+
+ }
+
+ } elsif ($line =~ /^stdout:(.*)$/) {
+ # LD_DEBUG stdout line:
+
+ $tmp = trim($1);
+ next if ($tmp eq '');
+
+ if ($tmp =~ /\s+=>\s+/) {
+ #
+ # First look for standard dependency
+ # resolution lines:
+ #
+ # libsocket.so.1 => /usr/lib/libsocket.so.1
+ #
+ # Note that these are *all* of the
+ # needed shared objects, not just the
+ # directly needed ones.
+ #
+ $tmp =~ s/\s+/ /g;
+ $neededs .= "NEEDED_FOUND:$tmp" . "\n";
+
+ } elsif ($tmp =~ /symbol not found: (.*)$/) {
+ #
+ # Next look for unbound symbols:
+ # symbol not found: gethz (/usr/\
+ # local/bin/gethz)
+ #
+
+ $tmp = trim($1);
+ ($tmp, $tmp2) = split(/\s+/, $tmp, 2);
+ $tmp2 =~ s/[\(\)]//g; # trim off ().
+
+ # $tmp is the symbol, $tmp2 is the
+ # calling object.
+
+ push(@bindings,
+ "BINDING_UNBOUND:$tmp2|$tmp" . "\n"
+ );
+ }
+ }
+ }
+
+ # Return the output:
+ my $ret = '';
+ $ret .= $filters if (defined($filters));
+ $ret .= $neededs if (defined($neededs));
+ $ret .= join('', @bindings);
+
+ return $ret;
+}
+
+#
+# Routine used to parse a LD_DEBUG "binding" line.
+#
+# Returns "preprocessed format line" if line is ok, or
+# null string otherwise.
+#
+sub ldd_binding_line
+{
+ my ($line, $object) = @_;
+
+ my ($from, $to, $sym);
+
+ my ($t1, $t2, $t3); # tmp vars for regex output
+
+ #
+ # Working on a line like:
+ #
+ # binding file=/bin/pagesize to file=/usr/lib/libc.so.1: symbol `exit'
+ #
+ # (with the leading "binding " removed).
+ #
+
+ if ($line =~ /^file=(\S+)\s+to file=(\S+)\s+symbol(.*)$/) {
+ #
+ # The following trim off spaces, ', `, ;, and :, from
+ # the edges so if the filename had those there could
+ # be a problem.
+ #
+ $from = $1;
+ $to = $2;
+ $sym = $3;
+ #
+ # guard against future changes to the LD_DEBUG output
+ # (i.e. information appended to the end)
+ #
+ $sym =~ s/'\s+.*$//;
+
+ $to =~ s/:$//;
+
+ $sym =~ s/[\s:;`']*$//;
+ $sym =~ s/^[\s:;`']*//;
+
+ } elsif ($line =~ /^file=(.+) to file=(.+): symbol (.*)$/) {
+ # This will catch spaces, but is less robust.
+ $t1 = $1;
+ $t2 = $2;
+ $t3 = $3;
+ #
+ # guard against future changes to the LD_DEBUG output
+ # (i.e. information appended to the end)
+ #
+ $t3 =~ s/'\s+.*$//;
+
+ $from = wclean($t1, 1);
+ $to = wclean($t2, 1);
+ $sym = wclean($t3);
+
+ } else {
+ return '';
+ }
+
+ if ($from eq '' || $to eq '' || $sym eq '') {
+ return '';
+ }
+
+ #
+ # OK, we have 3 files: $from, $to, $object
+ # Which, if any, are the same file?
+ #
+ # Note that we have not yet done the Filter library
+ # substitutions yet. So one cannot be too trusting of the file
+ # comparisons done here.
+ #
+
+ if (files_equal($from, $to, 0)) {
+ #
+ # We skip the "from" = "to" case
+ # (could call this: BINDING_SELF).
+ #
+ return '';
+ } elsif (files_equal($object, $from, 0)) {
+ # DIRECT CASE (object calls library):
+ return "BINDING_DIRECT:$from|$to|$sym" . "\n";
+ } elsif (files_equal($object, $to, 0)) {
+ # REVERSE CASE (library calls object):
+ return "BINDING_REVERSE:$from|$to|$sym" . "\n";
+ } else {
+ #
+ # INDIRECT CASE (needed library calls library):
+ # (this will not be a library calling itself because
+ # we skip $from eq $to above).
+ #
+ return "BINDING_INDIRECT:$from|$to|$sym" . "\n";
+ }
+}
+
+#
+# Routine used to parse a LD_DEBUG "filtered by" line.
+#
+# Returns "preprocessed format line" if line is ok, or null string
+# otherwise.
+#
+sub ldd_filter_line
+{
+ my ($line) = @_;
+
+ my ($filter, $filtee);
+
+ #
+ # Working on a line like:
+ #
+ # file=/usr/platform/SUNW,Ultra-1/lib/libc_psr.so.1; \
+ # filtered by /usr/lib/libc.so.1
+ #
+
+ my ($t1, $t2); # tmp vars for regex output
+
+ if ($line =~ /file=(\S+)\s+filtered by\s+(\S.*)$/) {
+ $t1 = $1;
+ $t2 = $2;
+ $filtee = wclean($t1);
+ $filter = wclean($t2);
+ } elsif ($line =~ /file=(.+); filtered by (.*)$/) {
+ $t1 = $1;
+ $t2 = $2;
+ $filtee = wclean($t1, 1);
+ $filter = wclean($t2, 1);
+ } else {
+ return '';
+ }
+
+ if ($filtee eq '' || $filter eq '') {
+ return '';
+ }
+ #
+ # What kind of filter is $filter?
+ # STANDARD (contains no "real code", e.g. libxnet.so.1), or
+ # AUXILIARY (provides "code" if needed, but
+ # prefers to pass filtee's "code", e.g. libc.so.1)
+ #
+ # LD_DEBUG output does not indicate this, so dump -Lv is run on it
+ # in filter_lib_type:
+ #
+
+ my $type = 'unknown';
+
+ $type = filter_lib_type($filter);
+
+ if ($type eq 'STD') {
+ return "FILTER_STD:$filter|$filtee" . "\n";
+ } elsif ($type eq 'AUX') {
+ return "FILTER_AUX:$filter|$filtee" . "\n";
+ } else {
+ return '';
+ }
+}
+
+#
+# Routine used to parse a LD_DEBUG "needed by" line.
+#
+# Returns "preprocessed format line" if line is ok, or the null string
+# otherwise.
+#
+sub ldd_needed_line
+{
+ my ($line, $object) = @_;
+
+ my ($thing_needed, $file);
+
+ my ($t1, $t2); # tmp variables for regex output.
+
+ #
+ # Working on a line like:
+ #
+ # file=libdl.so.1; needed by /usr/lib/libc.so.1
+ #
+
+ if ($line =~ /file=(\S+)\s+needed by\s+(\S.*)$/) {
+ $t1 = $1;
+ $t2 = $2;
+ $thing_needed = wclean($t1);
+ $file = wclean($t2);
+ } elsif ($line =~ /file=(.+); needed by (.*)$/) {
+ $t1 = $1;
+ $t2 = $2;
+ $thing_needed = wclean($t1, 1);
+ $file = wclean($t2, 1);
+ } else {
+ return '';
+ }
+
+ if ($thing_needed eq '' || $file eq '') {
+ return '';
+ }
+
+ #
+ # Note that $thing_needed is not a path to a file, just the
+ # short name unresolved, e.g. "libc.so.1". The next line of the
+ # LD_DEBUG output would tell us where $thing_needed is resolved
+ # to.
+ #
+
+ if (files_equal($object, $file)) {
+ return "NEEDED_DIRECT:$thing_needed|$file" . "\n";
+ } else {
+ return "NEEDED_INDIRECT:$thing_needed|$file" . "\n";
+ }
+}
+
+#
+# Routine to clean up a "word" string from ldd output.
+#
+# This is specialized for removing the stuff surrounding files and
+# symbols in the LD_DEBUG output. It is usually a file name or symbol
+# name.
+#
+sub wclean
+{
+ my ($w, $keep_space) = @_;
+
+ if (! $keep_space) {
+ # make sure leading/trailing spaces are gone.
+ $w =~ s/[\s:;`']*$//; # get rid of : ; ' and `
+ $w =~ s/^[\s:;`']*//;
+ } else {
+ $w =~ s/[:;`']*$//; # get rid of : ; ' and `
+ $w =~ s/^[:;`']*//;
+ }
+
+ return $w;
+}
+
+#
+# This routine runs ldd -r on the object file with LD_DEBUG flags turned
+# on. It collects the stdout and the LD_DEBUG profile data for the
+# object (it must skip the LD_DEBUG profile data for /usr/bin/ldd
+# /bin/sh, or any other extraneous processes).
+#
+# It returns the profile data as a single string with \n separated
+# records. Records starting with "stdout: " are the stdout lines,
+# Records starting with "NNNNN: " are the LD_DEBUG lines. Our caller
+# must split and parse those lines.
+#
+# If there is some non-fatal error, it returns a 1-line string like:
+# ERROR: <error-message>
+#
+sub get_ldd_output
+{
+
+ my ($object) = @_;
+
+ my ($tmpdir, $outfile, $errfile);
+
+ if (! -f $object) {
+ exiter(nopathexist($object));
+ }
+
+ # We use the tmp_dir for our work:
+ $tmpdir = $tmp_prof_dir;
+
+ # Clean out the tmpdir.
+ if ($tmpdir !~ m,^/*$,) {
+ unlink(<$tmpdir/*>);
+ #
+ # The following puts xgettext(1) back on track. It is
+ # confused and believes it is inside a C-style /* comment */
+ #
+ my $unused = "*/";
+ }
+
+ # Output files for collecting output of the ldd -r command:
+ $errfile = "$tmpdir/stderr";
+ $outfile = "$tmpdir/stdout";
+
+ my ($rc, $msg, $child, $result);
+
+ #
+ # This forking method should have 2 LD_DEBUG bind.<PID> files
+ # one for ldd and the other for $object. system() could have
+ # another from the shell.
+ #
+
+ # Fork off a child:
+ $child = fork();
+
+ #
+ # Note: the file "/tmp/.../bind.$child" should be the "ldd"
+ # profile, but we do not want to depend upon that.
+ #
+
+ if (! defined($child)) {
+ # Problem forking:
+ exiter(sprintf(gettext(
+ "cannot fork for command: ldd -r %s: %s\n"), $object, $!));
+
+ } elsif ($child == 0) {
+
+ # Reopen std output to the desired output files:
+ open(STDOUT, ">$outfile") ||
+ exiter(nofile($outfile, $!));
+
+ open(STDERR, ">$errfile") ||
+ exiter(nofile($errfile, $!));
+
+ #
+ # Set the env to turn on debugging from the linker:
+ #
+ $ENV{'LD_DEBUG'} = "files,bindings";
+ $ENV{'LD_DEBUG_OUTPUT'} = "$tmpdir/bind";
+
+ #
+ # Set LD_NOAUXFLTR to avoid auxiliary filters (e.g. libc_psr)
+ # since they are not of interest to the public/private
+ # symbol status and confuse things more than anything else.
+ #
+ $ENV{'LD_NOAUXFLTR'} = "1";
+
+ # Run ldd -r:
+ c_locale(1);
+ exec($cmd_ldd, '-r', $object);
+ exit 1; # only reached if exec fails.
+ } else {
+ wait; # Wait for children to finish.
+ $rc = $?; # Record exit status.
+ $msg = $!;
+ }
+
+ # Check the exit status:
+ if ($rc != 0) {
+ if (-s $errfile) {
+ my $tmp;
+ my $errfile_fh = do { local *FH; *FH };
+ if (open($errfile_fh, "<$errfile")) {
+ while (<$errfile_fh>) {
+ if (/ldd:/) {
+ $tmp = $_;
+ last;
+ }
+ }
+ close($errfile_fh);
+ }
+ if (defined($tmp)) {
+ chomp($tmp);
+ if ($tmp =~ /ldd:\s*(\S.*)$/) {
+ $tmp = $1;
+ }
+ if ($tmp =~ /^[^:]+:\s*(\S.*)$/) {
+ my $t = $1;
+ if ($t !~ /^\s*$/) {
+ $tmp = $t;
+ }
+ }
+ $msg = $tmp if ($tmp !~ /^\s*$/);
+ }
+ }
+ emsg("%s", norunprog("$cmd_ldd -r $object", "$msg\n"));
+ $msg =~ s/\n/ /g;
+ $msg =~ s/;/,/g;
+ $msg = sprintf("ERROR: " . gettext(
+ "Error running: ldd -r LD_DEBUG: %s"), $msg);
+ return $msg;
+ }
+
+ #
+ # We now have all the output files created. We read them and
+ # merge them into one long string to return to whoever called
+ # us. The caller will parse it, not us. Our goal here is to
+ # just return the correct LD_DEBUG profile data.
+ #
+
+ if (-f "$tmpdir/stdout") {
+ my $out_fh = do { local *FH; *FH };
+ if (! open($out_fh, "<$tmpdir/stdout")) {
+ exiter(nofile("$tmpdir/stdout", $!));
+ }
+ while (<$out_fh>) {
+ # Add the special prefix for STDOUT:
+ $result .= "stdout: $_";
+ }
+ close($out_fh);
+ }
+
+ my ($file, $count, $goodone, $ok, $aok, @file);
+
+ $count = 0;
+
+ my $prevline;
+
+ # Loop over each "bind.NNNNN" file in the tmp directory:
+ foreach $file (<$tmpdir/bind.*>) {
+
+ # Open it for reading:
+ my $ldd_file_fh = do { local *FH; *FH };
+ if (! open($ldd_file_fh, "<$file")) {
+ exiter(nofile($file, $!));
+ }
+
+ #
+ # ok = 1 means this file we are reading the profile file
+ # corresponding to $object. We set ok = 0 as soon as we
+ # discover otherwise.
+ #
+ $ok = 1;
+
+ #
+ # $aok = 1 means always OK. I.e. we are definitely in the
+ # correct profile.
+ #
+ $aok = 0;
+
+ #
+ # this variable will hold the previous line so that we
+ # can skip adjacent duplicates.
+ #
+ $prevline = '';
+
+ my $idx;
+
+ while (<$ldd_file_fh>) {
+
+ #
+ # This check is done to perform a simple
+ # uniq'ing of the output. Non-PIC objects have
+ # lots of duplicates, many of them right after
+ # each other.
+ #
+
+ next if ($_ eq $prevline);
+ $prevline = $_;
+
+ #
+ # Check to see if this is the wrong profile
+ # file: The ones we know about are "ldd" and
+ # "sh". If the object under test is ever "ldd"
+ # or "sh" this will fail.
+ #
+ if ($aok) {
+ ;
+ } elsif ($ok) {
+ #
+ # checks line:
+ # file=ldd; analyzing [ RTLD_GLOBAL RTLD_LAZY ]
+ #
+ if (/\bfile=\S+\b(ldd|sh)\b/) {
+ $ok = 0;
+ } else {
+ $idx =
+ index($_, " file=$object; analyzing");
+ $aok = 1 if ($idx != -1);
+ }
+ }
+
+ # We can skip this file as soon as we see $ok = 0.
+ last unless ($ok);
+
+ # Gather the profile output into a string:
+ $file[$count] .= $_;
+ }
+
+ #
+ # Note that this one is the desired profile
+ # (i.e. if $ok is still true):
+ #
+ $goodone .= "$count," if ($ok);
+
+ # On to the next $file:
+ close($ldd_file_fh);
+ $count++;
+ }
+
+ if (defined($goodone)) {
+ $goodone =~ s/,$//; # Trim the last comma off.
+ }
+
+ # If we have none or more than one "good one" we are in trouble:
+ if (! defined($goodone) || ($goodone !~ /^\d+$/) || ($goodone =~ /,/)) {
+
+ #
+ # Note that this is the first point at which we would detect
+ # a problem with the checking of SUID/SGID objects, although
+ # in theory we could have skipped these objects earlier.
+ # We prefer to let the linker, ld.so.1, indicate this failure
+ # and then we catch it and diagnose it here.
+ #
+ my $suid = is_suid($object);
+
+ if ($suid == 1) {
+ $result = "ERROR: " . gettext(
+ "SUID - ldd(1) LD_DEBUG profile failed");
+ } elsif ($suid == 2) {
+ $result = "ERROR: " . gettext(
+ "SGID - ldd(1) LD_DEBUG profile failed");
+ } else {
+ $result = "ERROR: " . gettext(
+ "could not get ldd(1) LD_DEBUG profile output");
+ }
+
+ } else {
+ # Append the correct profile to the result and return it:
+ $result .= $file[$goodone];
+ }
+
+ # Tidy up our mess by cleaning out the tmpdir.
+ unlink(<$tmpdir/*>) if ($tmpdir !~ m,^/*$,);
+
+ return $result;
+}
diff --git a/usr/src/cmd/abi/appcert/scripts/symreport.pl b/usr/src/cmd/abi/appcert/scripts/symreport.pl
new file mode 100644
index 0000000..36db632
--- /dev/null
+++ b/usr/src/cmd/abi/appcert/scripts/symreport.pl
@@ -0,0 +1,835 @@
+#!/usr/perl5/bin/perl -w
+#
+# 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) 1996-2000 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+
+#
+# This utility program reads the symcheck output of each binary and
+# creates additional output for then and an overall report.
+#
+
+require 5.005;
+use strict;
+use locale;
+use POSIX qw(locale_h);
+use Sun::Solaris::Utils qw(textdomain gettext);
+use File::Basename;
+use File::Path;
+
+use lib qw(/usr/lib/abi/appcert);
+use AppcertUtil;
+
+setlocale(LC_ALL, "");
+textdomain(TEXT_DOMAIN);
+
+use vars qw(
+ $tmp_report_dir
+ $misc_check_databases_loaded_ok
+ %result_list_hash
+ %result_msg
+ %warnings_found
+);
+
+set_clean_up_exit_routine(\&clean_up_exit);
+
+import_vars_from_environment();
+
+signals('on', \&interrupted);
+
+set_working_dir();
+
+generate_reports();
+
+clean_up();
+
+exit 0;
+
+#
+# working_dir has been imported by import_vars_from_environment()
+# A sanity check is performed here to make sure it exists.
+#
+sub set_working_dir
+{
+ if (! defined($working_dir) || ! -d $working_dir) {
+ exiter("$command_name: " . sprintf(gettext(
+ "cannot locate working directory: %s\n"), $working_dir));
+ }
+}
+
+#
+# Called when interrupted by user.
+#
+sub interrupted
+{
+ $SIG{$_[0]} = 'DEFAULT';
+ signals('off');
+ clean_up_exit(1);
+}
+
+#
+# Does the cleanup and then exit with return code $rc. Note: The
+# utility routine exiter() will call this routine.
+#
+sub clean_up_exit
+{
+ my ($rc) = @_;
+ $rc = 0 unless ($rc);
+
+ clean_up();
+ exit $rc;
+}
+
+#
+# General cleanup activities are placed here. There may not be an
+# immediate exit after this cleanup.
+#
+sub clean_up
+{
+ if (defined($tmp_report_dir) && -d $tmp_report_dir) {
+ rmtree($tmp_report_dir);
+ }
+}
+
+#
+# Top level routine for generating the additional reports.
+#
+sub generate_reports
+{
+ # Make a tmp dir for the reporting work.
+ $tmp_report_dir = create_tmp_dir($tmp_dir);
+
+ if (! -d $tmp_report_dir) {
+ exiter(nocreatedir($tmp_report_dir, $!));
+ }
+
+ pmsg("\n");
+ print_line();
+
+ my ($dir, $path_to_object);
+
+ #
+ # Loop over each object item in the working_dir.
+ # - $dir will be each one of these object directories.
+ # - $path_to_object will be the corresponding actual path
+ # to the the binary to be profiled.
+ # Output will be placed down in $dir, e.g. "$dir/report"
+ #
+
+ while (defined($dir = next_dir_name())) {
+
+ # Map object output dir to actual path of the object:
+ $path_to_object = dir_name_to_path($dir);
+
+ # Make a report for it:
+ report_object($path_to_object, $dir);
+ }
+
+ my $type;
+ foreach $type (keys(%result_list_hash)) {
+ $result_list_hash{$type} =~ s/\|+$//;
+ }
+
+ print_report();
+ my $tout;
+ $tout = gettext(
+ "Additional output regarding private symbols usage and other\n" .
+ "data is in the directory:\n");
+
+ $tout .= "\n $working_dir\n\n";
+
+ $tout .= gettext(
+ "see the appcert documentation for more information.\n");
+
+ pmsg("%s", $tout);
+
+ clean_up(); # Remove any tmp directories and files.
+}
+
+#
+# Examines the symcheck output for a given binary object recording and
+# reporting and problems found. Generates additional reports and
+# summaries.
+#
+sub report_object
+{
+ my ($object, $dir) = @_;
+
+ my (%problems);
+
+ my $problems_file = "$dir/check.problems";
+
+ my $problems_fh = do { local *FH; *FH };
+ open($problems_fh, "<$problems_file") ||
+ exiter(nofile($problems_file, $!));
+
+ # We need the "warning" msgs and text from the Misc Checks loaded:
+ if (! defined($misc_check_databases_loaded_ok)) {
+ $misc_check_databases_loaded_ok = load_misc_check_databases();
+ }
+
+ my ($prob, $incomp, $c, $w);
+ my $problem_count = 0;
+ my $incomplete_count = 0;
+ my $line_count = 0;
+
+ while (<$problems_fh>) {
+ chomp;
+ $prob = 1;
+ $incomp = 0;
+ $line_count++;
+
+ if (/^DYNAMIC: PRIVATE_SYMBOL_USE\s+(\d*)/) {
+ $problems{'private_syms'} += $1;
+ } elsif (/^DYNAMIC: UNBOUND_SYMBOL_USE\s+(\d*)/) {
+ $problems{'unbound_syms'} += $1;
+ $incomp = 1;
+ } elsif (/^DYNAMIC: UNRECOGNIZED_SYMBOL_USE\s+(\d*)/) {
+ $problems{'unrecognized_syms'} += $1;
+ $incomp = 1;
+ } elsif (/^DYNAMIC: NO_DYNAMIC_BINDINGS_FOUND\s*(.*)$/) {
+ $problems{'no_dynamic_bindings'} .= "$1, ";
+ $incomp = 1;
+ } elsif (/^STATIC: LINKED_ARCHIVE\s+(.*)$/) {
+ $problems{'static_linking'} .= "$1, ";
+ } elsif (/^STATIC: COMPLETELY_STATIC/) {
+ $problems{'completely_static'}++;
+ } elsif (/^MISC: REMOVED_SCOPED_SYMBOLS:\s+(.*)$/) {
+ $problems{'scoped_symbols'} .= "$1, ";
+ } elsif (/^MISC: WARNING:\s+(INCOMPLETE\S+)/) {
+ $problems{'warnings'} .= "$1|";
+ $incomp = 1;
+ } elsif (/^MISC: WARNING:\s+(.*)$/) {
+ $problems{'warnings'} .= "$1|";
+ } else {
+ $prob = 0;
+ }
+ $problem_count += $prob;
+ $incomplete_count += $incomp;
+ }
+ close($problems_fh);
+
+ if ($line_count == 0) {
+ # No problems at all, leave a comment message:
+ open($problems_fh, ">$problems_file") ||
+ exiter(nofile($problems_file, $!));
+ print $problems_fh "# NO_PROBLEMS_DETECTED\n";
+ close($problems_fh);
+ }
+
+ if ($problem_count == 0) {
+ $result_list_hash{'passed'} .= "$object|";
+ return;
+ }
+
+ if ($incomplete_count == $problem_count) {
+ $result_list_hash{'incomplete'} .= "$object|";
+ } else {
+ $result_list_hash{'failed'} .= "$object|";
+ }
+
+ my $m;
+
+ if ($m = $problems{'private_syms'}) {
+ $result_list_hash{'private_syms'} .= "$object|";
+ $result_msg{$object} .= "$m " .
+ gettext("private symbols") . "; ";
+ }
+
+ if ($m = $problems{'unbound_syms'}) {
+ $result_list_hash{'unbound_syms'} .= "$object|";
+ $result_msg{$object} .= "$m " .
+ gettext("unbound symbols") . "; ";
+
+ # add this case to the warnings output at end of report.
+ my $tag = 'unbound symbols';
+ $warnings_found{$tag} .= "$object|";
+
+ if (! exists($warnings_desc{$tag})) {
+ my $desc = gettext("unbound symbols");
+ $warnings_desc{$tag} = $desc;
+ }
+ }
+
+ if ($m = $problems{'unrecognized_syms'}) {
+ $result_list_hash{'unrecognized_syms'} .= "$object|";
+ $result_msg{$object} .= "$m " .
+ gettext("unrecognized symbols") . "; ";
+
+ # Add this case to the warnings output at end of report.
+ my $tag = 'unrecognized symbols';
+ $warnings_found{$tag} .= "$object|";
+
+ if (! exists($warnings_desc{$tag})) {
+ my $desc = gettext("unrecognized symbols");
+ $warnings_desc{$tag} = $desc;
+ }
+ }
+
+ if ($m = $problems{'static_linking'}) {
+ $result_list_hash{'static_linking'} .= "$object|";
+ $m =~ s/,\s*$//;
+ $result_msg{$object} .= sprintf(gettext(
+ "statically linked with %s"), $m) . "; ";
+
+ # Add this case to the warnings output at end of report.
+ my $tag = 'statically linked';
+ $warnings_found{$tag} .= "$object|";
+
+ if (! exists($warnings_desc{$tag})) {
+ my $desc =
+ gettext("static linking of Solaris libraries");
+ $warnings_desc{$tag} = $desc;
+ }
+ }
+
+ if ($problems{'completely_static'}) {
+ $result_list_hash{'completely_static'} .= "$object|";
+ $result_msg{$object} .=
+ gettext("completely statically linked") . "; ";
+
+ # Add this case to the warnings output.
+ my $tag = gettext("completely statically linked");
+ $warnings_found{$tag} .= "$object|";
+
+ my $desc =
+ gettext("complete static linking of Solaris libraries");
+ if (! exists($warnings_desc{$tag})) {
+ $warnings_desc{$tag} = $desc;
+ }
+
+ } elsif ($m = $problems{'no_dynamic_bindings'}) {
+ #
+ # Note we skip this error if it is completely static.
+ # The app could technically be SUID as well.
+ #
+
+ $result_list_hash{'no_dynamic_bindings'} .= "$object|";
+ $m =~ s/,\s*$//;
+ $m = " : $m";
+ $m =~ s/ : NO_SYMBOL_BINDINGS_FOUND//;
+ $m =~ s/^ :/:/;
+ $result_msg{$object} .=
+ gettext("no bindings found") . "$m; ";
+ }
+
+ if ($m = $problems{'scoped_symbols'}) {
+ $m =~ s/[,\s]*$//;
+ $result_list_hash{'scoped_symbols'} .= "$object|";
+ $c = scalar(my @a = split(' ', $m));
+
+ $result_msg{$object} .= "$c " .
+ gettext("demoted (removed) private symbols") . ": $m; ";
+
+ # Add this case to the warnings output.
+ my $tag = 'scoped symbols';
+ $warnings_found{$tag} .= "$object|";
+
+ my $desc = gettext(
+ "dependency on demoted (removed) private Solaris symbols");
+ if (! exists($warnings_desc{$tag})) {
+ $warnings_desc{$tag} = $desc;
+ }
+ }
+
+ if ($m = $problems{'warnings'}) {
+ foreach $w (split(/\|/, $m)) {
+ next if ($w =~ /^\s*$/);
+
+ $c = $w;
+ if (defined($warnings_desc{$c})) {
+ $c = $warnings_desc{$c};
+ $c = gettext($c);
+ }
+ $c =~ s/;//g;
+ $result_msg{$object} .= "$c; ";
+ $warnings_found{$w} .= "$object|";
+ }
+ }
+
+ $result_msg{$object} =~ s/;\s+$//;
+}
+
+#
+# Create the top level roll-up report.
+#
+sub print_report
+{
+ # Count the number of passed, failed and total binary objects:
+ my(@a);
+ my($r_passed, $r_incomp, $r_failed);
+ if (exists($result_list_hash{'passed'})) {
+ $r_passed = $result_list_hash{'passed'};
+ } else {
+ $r_passed = '';
+ }
+ if (exists($result_list_hash{'incomplete'})) {
+ $r_incomp = $result_list_hash{'incomplete'};
+ } else {
+ $r_incomp = '';
+ }
+ if (exists($result_list_hash{'failed'})) {
+ $r_failed = $result_list_hash{'failed'};
+ } else {
+ $r_failed = '';
+ }
+ my $n_passed = scalar(@a = split(/\|/, $r_passed));
+ my $n_incomp = scalar(@a = split(/\|/, $r_incomp));
+ my $n_failed = scalar(@a = split(/\|/, $r_failed));
+ my $n_checked = $n_passed + $n_incomp + $n_failed;
+
+ my ($summary_result, $msg, $output, $object);
+
+
+ if ($n_checked == 0) {
+ $summary_result = $text{'Summary_Result_None_Checked'};
+ } elsif ($n_failed > 0) {
+ $summary_result = $text{'Summary_Result_Some_Failed'};
+ } elsif ($n_incomp > 0) {
+ $summary_result = $text{'Summary_Result_Some_Incomplete'};
+ } else {
+ $summary_result = $text{'Summary_Result_All_Passed'};
+ }
+
+ # place the info in problem count file:
+ my $cnt_file = "$working_dir/ProblemCount";
+ my $pcount_fh = do { local *FH; *FH };
+ if (! open($pcount_fh, ">$cnt_file")) {
+ exiter(nofile($cnt_file, $!));
+ }
+
+ print $pcount_fh "$n_failed / $n_checked binary_objects_had_problems\n";
+ print $pcount_fh
+ "$n_incomp / $n_checked could_not_be_completely_checked\n";
+
+ print $pcount_fh "NO_PROBLEMS_LIST: $r_passed\n";
+ print $pcount_fh "INCOMPLETE_LIST: $r_incomp\n";
+ print $pcount_fh "PROBLEMS_LIST: $r_failed\n";
+ close($pcount_fh);
+
+ #
+ # Set the overall result code.
+ # This is used to communicate back to the appcert script to
+ # indicate how it should exit(). The string must start with the
+ # exit number, after which a message may follow.
+ #
+
+ if ($n_checked == 0) {
+ overall_result_code("3 => nothing_checked");
+ } elsif ($n_failed > 0) {
+ overall_result_code("2 => some_problems_detected($n_failed)");
+ } elsif ($n_incomp > 0) {
+ overall_result_code("1 => " .
+ "some_binaries_incompletely_checked($n_incomp)");
+ } else {
+ overall_result_code("0 => no_problems_detected");
+ }
+
+ my ($sp0, $sp, $sf, $si); # PASS & FAIL spacing tags.
+ $sp0 = ' ';
+ if ($batch_report) {
+ $sp = 'PASS ';
+ $sf = 'FAIL ';
+ $si = 'INC ';
+ } else {
+ $sp = $sp0;
+ $sf = $sp0;
+ $si = $sp0;
+ }
+
+
+ $msg = sprintf(gettext("Summary: %s"), $summary_result) . "\n\n";
+ my $format = gettext("A total of %d binary objects were examined.");
+ $msg .= sprintf($format, $n_checked) . "\n\n\n";
+ $output .= $msg;
+
+ my $fmt1 = gettext(
+ "The following (%d of %d) components had no problems detected:");
+
+ if ($n_passed > 0) {
+ $output .= sprintf($fmt1, $n_passed, $n_checked);
+ $output .= "\n\n";
+
+ foreach $object (split(/\|/, $r_passed)) {
+ $output .= "${sp}$object\n";
+ }
+ $output .= "\n";
+ }
+
+ my $fmt2 = gettext(
+ "The following (%d of %d) components had no problems detected,\n" .
+ " but could not be completely checked:");
+
+ if ($n_incomp > 0) {
+ $output .= sprintf($fmt2, $n_incomp, $n_checked);
+ $output .= "\n\n";
+
+ foreach $object (split(/\|/, $r_incomp)) {
+ $msg = $result_msg{$object};
+ $output .= "${si}$object\t($msg)\n";
+ }
+ $output .= "\n";
+ }
+
+ my $fmt3 = gettext(
+ "The following (%d of %d) components have potential " .
+ "stability problems:");
+ if ($n_failed > 0) {
+ $output .= sprintf($fmt3, $n_failed, $n_checked);
+ $output .= "\n\n";
+
+ foreach $object (split(/\|/, $r_failed)) {
+ $msg = $result_msg{$object};
+ $output .= "${sf}$object\t($msg)\n";
+ }
+ $output .= "\n";
+ }
+
+ $output .= "\n" . get_summary();
+
+ $output .= "\n" . get_warnings();
+
+ my $report_file = "$working_dir/Report";
+ my $report_fh = do { local *FH; *FH };
+ open($report_fh, ">$report_file") ||
+ exiter(nofile($report_file, $!));
+
+ print $report_fh $output;
+ close($report_fh);
+ system($cmd_more, $report_file);
+}
+
+#
+# Collects all of the warnings issued for the binaries that were
+# checked. Returns the warning text that will go into the roll-up
+# report.
+#
+sub get_warnings
+{
+ my ($w, $c, $output, $count);
+
+ if (! %warnings_found) {
+ return ''; # appends null string to output text
+ }
+
+ $output = gettext("Summary of various warnings:") . "\n\n";
+ my(@a);
+ foreach $w (keys(%warnings_found)) {
+ $warnings_found{$w} =~ s/\|+$//;
+ $count = scalar(@a = split(/\|/, $warnings_found{$w}));
+ $c = $w;
+ if (defined($warnings_desc{$c})) {
+ $c = $warnings_desc{$c};
+ }
+ $c = gettext($c);
+ $output .= " - $c " . sprintf(gettext(
+ "(%d binaries)\n"), $count);
+ $output .= "\n";
+
+ }
+ $output .= "\n";
+
+ return $output;
+}
+
+#
+# Computes the summary information for each binary object that was
+# checked. Returns the text that will go into the roll-up report.
+#
+sub get_summary
+{
+ my ($dir, $file);
+ my (%lib_private, %libsym_private);
+ my (%libapp, %libapp_private);
+
+ my ($bin, $arch, $direct, $lib, $class, $sym);
+
+ while (defined($dir = next_dir_name())) {
+
+ # This is where the public symbol list is:
+ $file = "$dir/check.dynamic.public";
+
+ my %app_public;
+ my %app_sym_public;
+ my %app_private;
+ my %app_sym_private;
+
+ if (-s $file) {
+ my $publics_fh = do { local *FH; *FH };
+ open($publics_fh, "<$file") ||
+ exiter(nofile($file, $!));
+
+ while (<$publics_fh>) {
+ next if (/^\s*#/);
+ chomp;
+ ($bin, $arch, $direct, $lib, $class, $sym) =
+ split(/\|/, $_);
+
+ $libapp{"$lib|$bin"}++;
+
+ $app_public{$lib}++;
+ $app_sym_public{"$lib|$sym"}++;
+ }
+ close($publics_fh);
+ }
+
+ # This is where the private symbol list is:
+ $file = "$dir/check.dynamic.private";
+
+ if (-s $file) {
+ my $privates_fh = do { local *FH; *FH };
+ open($privates_fh, "<$file") ||
+ exiter(nofile($file, $!));
+
+ while (<$privates_fh>) {
+ next if (/^\s*#/);
+ chomp;
+ ($bin, $arch, $direct, $lib, $class, $sym) =
+ split(/\|/, $_);
+
+ $lib_private{$lib}++;
+ $libsym_private{"$lib|$sym"}++;
+ $libapp_private{"$lib|$bin"}++;
+ $libapp{"$lib|$bin"}++;
+
+ $app_private{$lib}++;
+ $app_sym_private{"$lib|$sym"}++;
+ }
+ close($privates_fh);
+ }
+
+ write_app_summary($dir, \%app_public, \%app_sym_public,
+ \%app_private, \%app_sym_private);
+ }
+
+ my ($app_total, $app_private_total);
+ my ($key, $lib2, $app2, $sym2);
+ my $val;
+ my $text;
+
+ foreach $lib (sort(keys(%lib_private))) {
+
+ $app_total = 0;
+ foreach $key (keys(%libapp)) {
+ ($lib2, $app2) = split(/\|/, $key);
+ $app_total++ if ($lib eq $lib2);
+ }
+
+ $app_private_total = 0;
+ foreach $key (keys(%libapp_private)) {
+ ($lib2, $app2) = split(/\|/, $key);
+ $app_private_total++ if ($lib eq $lib2);
+ }
+
+ my @list;
+ while (($key, $val) = each(%libsym_private)) {
+ ($lib2, $sym2) = split(/\|/, $key);
+ next unless ($lib eq $lib2);
+ push(@list, "$sym2 $val");
+
+ }
+
+ $text .= private_format($lib, $app_total,
+ $app_private_total, @list);
+ }
+
+ if (! defined($text)) {
+ return ''; # appends null string to output report.
+ }
+ return $text;
+}
+
+#
+# Given the symbols and counts of private symbols used by all binaries
+# that were checked, returns a pretty-printed format table of the
+# symbols. This text goes into the roll-up report and the summary.dynamic
+# file.
+#
+sub private_format
+{
+ my ($lib, $tot, $priv, @list) = @_;
+
+ my (@sorted) = sort_on_count(@list);
+ my $formatted = list_format(' ', @sorted);
+
+ my $text;
+ my $libbase = basename($lib);
+
+ $text = sprintf(gettext(
+ "Summary of Private symbol use in %s\n"), $lib);
+ my $fmt =
+ gettext("%d binaries used %s, %d of these used private symbols");
+ $text .= sprintf($fmt, $tot, $libbase, $priv);
+ $text .= "\n\n$formatted\n";
+
+ return $text;
+}
+
+#
+# Given the public/private symbol and library usage information for a
+# binary object, creates an output file with this information formatted
+# in tables.
+#
+sub write_app_summary
+{
+ my ($dir, $public, $sym_public, $private, $sym_private) = @_;
+
+ my $outfile = "$dir/summary.dynamic";
+
+ my $summary_fh = do { local *FH; *FH };
+ open($summary_fh, ">$outfile") ||
+ exiter(nofile($outfile, $!));
+
+ my $path_to_object = dir_name_to_path($dir);
+
+
+ my ($tmp1, $tmp2, $tmp3);
+
+ $tmp1 = gettext("ABI SYMBOL USAGE SUMMARY REPORT");
+ $tmp2 = '*' x length($tmp1);
+
+ print $summary_fh "$tmp2\n$tmp1\n$tmp2\n\n";
+
+ print $summary_fh " ", sprintf(gettext(
+ "Binary Object: %s\n"), $path_to_object);
+
+ my $uname_a = `$cmd_uname -a`;
+ print $summary_fh " ", sprintf(gettext("System: %s\n"), $uname_a);
+
+ $tmp1 = gettext("References to shared objects in the Solaris ABI");
+ $tmp2 = '*' x length($tmp1);
+
+ print $summary_fh "$tmp2\n$tmp1\n$tmp2\n\n";
+
+
+ my (%libs, $lib, $maxlen, $len);
+ $maxlen = 0;
+
+ foreach $lib (keys(%$public), keys(%$private)) {
+ $len = length($lib);
+ $maxlen = $len if ($len > $maxlen);
+ $libs{$lib} = 1;
+ }
+
+ if (! %libs) {
+ my $str = gettext(
+ " NONE FOUND. Possible explanations:\n" .
+ " - the dynamic profiling failed, see ldd(1), ld.so.1(1)\n" .
+ " - the object is SUID or SGID\n" .
+ " - the object is completely statically linked.\n"
+ );
+ print $summary_fh $str, "\n";
+ close($summary_fh);
+ return;
+ }
+
+ foreach $lib (sort(keys(%libs))) {
+ print $summary_fh " $lib\n";
+ }
+ print $summary_fh "\n";
+
+ my ($len1, $len2, $len3);
+ my $heading = ' ' . gettext("Library");
+ $heading .= ' ' x ($maxlen + 6 - length($heading));
+ $len1 = length($heading) - 2;
+ my $public_str = gettext("Public");
+ $len2 = length($public_str);
+ my $private_str = gettext("Private");
+ $len3 = length(" $private_str");
+ $heading .= "$public_str $private_str";
+ $tmp3 = $heading;
+ $tmp3 =~ s/\S/-/g;
+
+ $tmp1 = gettext("Symbol usage statistics (summary by shared object)");
+ $tmp2 = '*' x length($tmp1);
+
+ print $summary_fh "$tmp2\n$tmp1\n$tmp2\n\n";
+ print $summary_fh "$heading\n";
+ print $summary_fh "$tmp3\n";
+
+ my ($pub, $priv, $str);
+ foreach $lib (sort(keys(%libs))) {
+ $pub = $public->{$lib};
+ $priv = $private->{$lib};
+
+ $pub = 0 if (! defined($pub));
+ $priv = 0 if (! defined($priv));
+
+ $str = ' ';
+ $str .= sprintf("%-${len1}s", $lib);
+ $str .= sprintf("%${len2}s", $pub);
+ $str .= sprintf("%${len3}s", $priv);
+ print $summary_fh $str, "\n";
+ }
+ print $summary_fh "\n";
+
+ $tmp1 = gettext("Symbol usage (detailed inventory by shared object)");
+ $tmp2 = '*' x length($tmp1);
+
+ print $summary_fh "$tmp2\n$tmp1\n$tmp2\n\n";
+
+ my (@pub, @priv, $lib2, $sym2, $text, $key);
+ foreach $lib (sort(keys(%libs))) {
+ @pub = ();
+ @priv = ();
+
+ foreach $key (keys(%$sym_public)) {
+ next unless (index($key, $lib) == 0);
+ ($lib2, $sym2) = split(/\|/, $key, 2);
+ next unless ($lib2 eq $lib);
+ push(@pub, $sym2);
+ }
+ foreach $key (keys(%$sym_private)) {
+ next unless (index($key, $lib) == 0);
+ ($lib2, $sym2) = split(/\|/, $key, 2);
+ next unless ($lib2 eq $lib);
+ push(@priv, $sym2);
+ }
+
+ next if (! @pub && ! @priv);
+
+ my $fmt = gettext("Symbols in %s Directly Referenced");
+ $text = sprintf($fmt, $lib);
+
+ if (@pub) {
+ $lib2 = scalar(@pub);
+ $text .= sprintf(gettext(
+ " %d public symbols are used:\n"), $lib2);
+ $text .= list_format(' ', sort(@pub));
+ $text .= "\n";
+ }
+ if (@priv) {
+ $lib2 = scalar(@priv);
+ $text .= sprintf(gettext(
+ " %d private symbols are used:\n"), $lib2);
+ $text .= list_format(' ', sort(@priv));
+ $text .= "\n";
+ }
+
+ print $summary_fh $text;
+ }
+ close($summary_fh);
+}
diff --git a/usr/src/cmd/abi/appcert/static_prof/Makefile b/usr/src/cmd/abi/appcert/static_prof/Makefile
new file mode 100644
index 0000000..7ede955
--- /dev/null
+++ b/usr/src/cmd/abi/appcert/static_prof/Makefile
@@ -0,0 +1,50 @@
+#
+# 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) 1996-2000 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# cmd/abi/appcert/static_prof/Makefile
+#
+
+include $(SRC)/Makefile.master
+
+SUBDIRS= $(MACH)
+
+all:= TARGET= all
+install:= TARGET= install
+clean:= TARGET= clean
+clobber:= TARGET= clobber
+lint:= TARGET= lint
+
+.KEEP_STATE:
+
+all clean clobber lint: $(SUBDIRS)
+
+install: $(SUBDIRS)
+
+$(MACH): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
diff --git a/usr/src/cmd/abi/appcert/static_prof/Makefile.com b/usr/src/cmd/abi/appcert/static_prof/Makefile.com
new file mode 100644
index 0000000..3d9f48b
--- /dev/null
+++ b/usr/src/cmd/abi/appcert/static_prof/Makefile.com
@@ -0,0 +1,51 @@
+#
+# 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) 1997-2000 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# cmd/abi/appcert/static_prof/Makefile.com
+#
+
+include $(SRC)/cmd/Makefile.cmd
+
+PROG = static_prof
+SRCS = $(PROG:%=../%.c)
+
+# CPPFLAGS = -I..
+CFLAGS += $(LDLIBS)
+LDLIBS = -lelf
+
+LINTFLAGS = -nmxsuF -errtags=yes
+LINTLIBS += $(LDLIBS)
+
+CLEANFILES += $(PROG)
+CLOBBERFILES += $(PROG)
+
+#
+# Installed items
+#
+ROOTLIB_APPCERT= $(ROOT)/usr/lib/abi/appcert
+ROOTLIB_APPCERT_PROG= $(PROG:%=$(ROOTLIB_APPCERT)/%)
+
diff --git a/usr/src/cmd/abi/appcert/static_prof/Makefile.targ b/usr/src/cmd/abi/appcert/static_prof/Makefile.targ
new file mode 100644
index 0000000..aaf0eb1
--- /dev/null
+++ b/usr/src/cmd/abi/appcert/static_prof/Makefile.targ
@@ -0,0 +1,56 @@
+#
+# 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) 1997-2000 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# cmd/abi/appcert/static_prof/Makefile
+#
+
+$(PROG): $(SRCS)
+ $(LINK.c) -o $@ $(SRCS)
+ $(POST_PROCESS)
+
+#
+# clean - (apparently needs an explicit directive)
+#
+clean:
+ -$(RM) $(PROG)
+
+#
+# lint - (apparently needs an explicit dependency on lint_PROG or lint_SRCS)
+#
+lint: lint_SRCS
+
+#
+# Install targets
+#
+$(ROOTLIB_APPCERT)/%: %
+ $(INS.file)
+
+$(ROOTLIB_APPCERT):
+ $(INS.dir)
+
+include $(SRC)/cmd/Makefile.targ
+
diff --git a/usr/src/cmd/abi/appcert/static_prof/i386/Makefile b/usr/src/cmd/abi/appcert/static_prof/i386/Makefile
new file mode 100644
index 0000000..5b6caed
--- /dev/null
+++ b/usr/src/cmd/abi/appcert/static_prof/i386/Makefile
@@ -0,0 +1,37 @@
+#
+# 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) 1996-2000 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+install: all $(ROOTLIB_APPCERT) $(ROOTLIB_APPCERT_PROG)
+
+include ../Makefile.targ
diff --git a/usr/src/cmd/abi/appcert/static_prof/sparc/Makefile b/usr/src/cmd/abi/appcert/static_prof/sparc/Makefile
new file mode 100644
index 0000000..5b6caed
--- /dev/null
+++ b/usr/src/cmd/abi/appcert/static_prof/sparc/Makefile
@@ -0,0 +1,37 @@
+#
+# 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) 1996-2000 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+install: all $(ROOTLIB_APPCERT) $(ROOTLIB_APPCERT_PROG)
+
+include ../Makefile.targ
diff --git a/usr/src/cmd/abi/appcert/static_prof/static_prof.c b/usr/src/cmd/abi/appcert/static_prof/static_prof.c
new file mode 100644
index 0000000..297dc7d
--- /dev/null
+++ b/usr/src/cmd/abi/appcert/static_prof/static_prof.c
@@ -0,0 +1,1753 @@
+/*
+ * 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.
+ */
+
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+
+/* ------------------------------------------------------------------------ */
+/* include headers */
+/* ------------------------------------------------------------------------ */
+
+#include "static_prof.h"
+
+/* ========== elf_hash ==================================================== */
+/*
+ * DESCRIPTION:
+ * The hash function copied from libelf.so.1
+ */
+/* ======================================================================== */
+
+static unsigned long
+my_elf_hash(const char *name)
+{
+ unsigned long g, h = 0;
+ const unsigned char *nm = (unsigned char *) name;
+
+ while (*nm != '\0') {
+ h = (h << 4) + *nm++;
+ if ((g = h & MASK) != 0)
+ h ^= g >> 24;
+ h &= ~MASK;
+ }
+ return (h);
+}
+
+/* ========== output_dtneeded ============================================= */
+/*
+ * DESCRIPTION:
+ * Outputs all the dt_needed entries if any.
+ */
+/* ======================================================================== */
+
+static void
+output_dtneeded(dt_list * list)
+{
+
+ dt_list *p = list;
+
+ (void) fprintf(OUTPUT_FD, "#dtneeded:");
+ if (!p) {
+ (void) fprintf(OUTPUT_FD, "\n");
+ return;
+ } else {
+ while (p != NULL) {
+ (void) fprintf(OUTPUT_FD,
+ " %s",
+ p->libname);
+ p = p->next;
+ }
+ (void) fprintf(OUTPUT_FD, "\n");
+ }
+}
+
+/* ========== store_binding =============================================== */
+/*
+ * DESCRIPTION:
+ * Read in the symbol binding information from the symbol table and
+ * store them into the hash table of buckets.
+ */
+/* ======================================================================== */
+
+static void
+store_binding(binding_bucket * bind)
+{
+ unsigned long bktno;
+ unsigned long orig_bktno;
+ int table_full = FALSE;
+ int i;
+
+ bktno = my_elf_hash(bind->sym) % DEFBKTS;
+ orig_bktno = bktno;
+
+ if (!bkts[bktno].sym) {
+ bkts[bktno].sym = bind->sym;
+ bkts[bktno].obj = bind->obj;
+ bkts[bktno].ref_lib = bind->ref_lib;
+ bkts[bktno].def_lib = bind->def_lib;
+ bkts[bktno].section = bind->section;
+ bkts[bktno].stbind = bind->stbind;
+ bkts[bktno].sttype = bind->sttype;
+ } else {
+ bktno = (bktno + 1) % DEFBKTS;
+ for (i = bktno; i < DEFBKTS; i = (i + 1) % DEFBKTS) {
+ if (i == orig_bktno) {
+ table_full = TRUE;
+ exit(1);
+ }
+ if (!bkts[i].sym)
+ break;
+ }
+ if ((!bkts[i].sym) && (table_full != TRUE)) {
+ bkts[i].sym = bind->sym;
+ bkts[i].obj = bind->obj;
+ bkts[i].ref_lib = bind->ref_lib;
+ bkts[i].def_lib = bind->def_lib;
+ bkts[i].section = bind->section;
+ bkts[i].stbind = bind->stbind;
+ bkts[i].sttype = bind->sttype;
+ }
+ }
+}
+
+/* ========== check_store_binding ========================================= */
+/*
+ * DESCRIPTION:
+ * Check what's already on the hash table with the new symbol binding
+ * information from the dependencies and record it into the bucket.
+ */
+/* ======================================================================== */
+
+static void
+check_store_binding(binding_bucket * bind)
+{
+ unsigned long bktno;
+ unsigned long orig_bktno;
+ unsigned long i;
+
+ bktno = my_elf_hash(bind->sym) % DEFBKTS;
+ orig_bktno = bktno;
+
+ if (!bkts[bktno].sym)
+ return;
+ if (bkts[bktno].sym && (strcmp(bkts[bktno].sym, bind->sym)) == 0) {
+ if (strcmp(bkts[bktno].ref_lib, "<Unknown>") == 0)
+ if (strcmp(bkts[bktno].obj, bind->obj))
+ bkts[bktno].ref_lib = bind->obj;
+ } else {
+ bktno = (bktno + 1) % DEFBKTS;
+ for (i = bktno; i < DEFBKTS; i = (i + 1) % DEFBKTS) {
+ if (i == orig_bktno)
+ break;
+ if (!bkts[i].sym)
+ continue;
+ if (bkts[i].sym &&
+ (strcmp(bkts[i].sym, bind->sym)) == 0) {
+ if (strcmp(bkts[i].ref_lib, "<Unknown>") == 0)
+ if (strcmp(bkts[i].obj, bind->obj))
+ bkts[i].ref_lib = bind->obj;
+ break;
+ }
+ }
+ }
+}
+
+/* ========== stringcompare =============================================== */
+/*
+ * DESCRIPTION:
+ * Compares two strings for qsort().
+ */
+/* ======================================================================== */
+
+static int
+stringcompare(binding_bucket * a,
+ binding_bucket * b)
+{
+ char *x = "\0";
+ char *y = "\0";
+ int retcode;
+
+ if (a->sym)
+ x = a->sym;
+
+ if (b->sym)
+ y = b->sym;
+
+ retcode = strcoll(x, y);
+ return (retcode);
+}
+
+/* ========== profile_binding ============================================= */
+/*
+ * DESCRIPTION:
+ * Output the bindings directly to stdout or a file.
+ */
+/* ======================================================================== */
+
+static void
+profile_binding(binding_bucket * bind)
+{
+ char *ref_lib_ptr;
+
+ if (bind->sym && strcmp(bind->ref_lib, "<Unknown>")) {
+ if (ref_lib_ptr = strrchr(bind->ref_lib, (int)'/')) {
+ ref_lib_ptr++;
+ if (bind->stbind)
+ (void) fprintf(OUTPUT_FD,
+ "%s|%s|%s|%s|%s|%s|%s\n",
+ ref_lib_ptr,
+ bind->section,
+ bind->stbind,
+ bind->sttype,
+ bind->sym,
+ bind->def_lib,
+ bind->obj);
+ } else if (bind->stbind)
+ (void) fprintf(OUTPUT_FD,
+ "%s|%s|%s|%s|%s|%s|%s\n",
+ bind->ref_lib,
+ bind->section,
+ bind->stbind,
+ bind->sttype,
+ bind->sym,
+ bind->def_lib,
+ bind->obj);
+ } else if (bind->sym && bind->stbind)
+ (void) fprintf(OUTPUT_FD,
+ "%s|%s|%s|%s|%s\n",
+ bind->obj,
+ bind->section,
+ bind->stbind,
+ bind->sttype,
+ bind->sym);
+}
+
+/* ========== output_binding ============================================== */
+/*
+ * DESCRIPTION:
+ * Output the hash table to either stdout or a file.
+ */
+/* ======================================================================== */
+
+static void
+output_binding(char *prog_name,
+ char *target)
+{
+ int i;
+ char *ref_lib_ptr;
+
+ qsort(bkts,
+ DEFBKTS,
+ sizeof (binding_bucket),
+ (int (*) (const void *, const void *)) stringcompare);
+
+ if (oflag) {
+ if ((OUTPUT_FD = fopen(outputfile, "w")) == NULL) {
+ if (sflag)
+ (void) fprintf(stderr,
+ "\nfopen failed to open <%s>...\n\n",
+ outputfile);
+ exit(1);
+ }
+ }
+ /* generates profile report */
+ (void) fprintf(OUTPUT_FD,
+ "#generated by %s\n",
+ prog_name);
+ (void) fprintf(OUTPUT_FD,
+ "#profiling symbols in .text section of %s\n",
+ target);
+ output_dtneeded(dt_needed);
+
+ for (i = 0; i < DEFBKTS; i++) {
+ if (bkts[i].sym && strcmp(bkts[i].ref_lib, "<Unknown>")) {
+ if (ref_lib_ptr = strrchr(bkts[i].ref_lib, (int)'/')) {
+ ref_lib_ptr++;
+ if (bkts[i].stbind)
+ (void) fprintf(OUTPUT_FD,
+ "%s|%s|%s|%s|%s|%s|%s\n",
+ ref_lib_ptr,
+ bkts[i].section,
+ bkts[i].stbind,
+ bkts[i].sttype,
+ bkts[i].sym,
+ bkts[i].def_lib,
+ bkts[i].obj);
+ } else if (bkts[i].stbind)
+ (void) fprintf(OUTPUT_FD,
+ "%s|%s|%s|%s|%s|%s|%s\n",
+ bkts[i].ref_lib,
+ bkts[i].section,
+ bkts[i].stbind,
+ bkts[i].sttype,
+ bkts[i].sym,
+ bkts[i].def_lib,
+ bkts[i].obj);
+ } else if (bkts[i].sym && bkts[i].stbind)
+ (void) fprintf(OUTPUT_FD,
+ "%s|%s|%s|%s|%s\n",
+ bkts[i].obj,
+ bkts[i].section,
+ bkts[i].stbind,
+ bkts[i].sttype,
+ bkts[i].sym);
+ }
+}
+
+/* ========== obj_init ==================================================== */
+/*
+ * DESCRIPTION:
+ * Open (object) file, get ELF descriptor, and verify that the file is
+ * an ELF file.
+ */
+/* ======================================================================== */
+
+static int
+obj_init(obj_list * c)
+{
+ int mode = O_RDONLY;
+
+ /* open the file */
+ if ((c->obj->fd = open(c->obj->ename, mode)) < 0) {
+ if (sflag) {
+ if (errno == ENOENT)
+ (void) fprintf(stderr,
+ "Cannot open <<%s>> : \
+ No such file or directory.\n",
+ c->obj->ename);
+ else if (errno == EMFILE)
+ (void) fprintf(stderr,
+ "File <<%s>> : Already opened.\n",
+ c->obj->ename);
+ }
+ c->obj->fd = NULL;
+ return (FAIL);
+ }
+ /*
+ * queries the ELF library's internal version.
+ * Passing ver equal to EV_NONE causes elf_version() to return
+ * the library's internal version, without altering the working
+ * version. If ver is a version known to the library,
+ * elf_version() returns the previous or initial working
+ * version number. Otherwise, the working version remains
+ * unchanged and elf_version() returns EV_NONE.
+ */
+
+ /* check if libelf.so is at the right level */
+ if (elf_version(EV_CURRENT) == EV_NONE) {
+ if (sflag)
+ (void) fprintf(stderr,
+ "Library out of date in ELF access routines.\n");
+ return (FAIL);
+ }
+ /*
+ * Before the first call to elf_begin(), it must call
+ * elf_version() to coordinate versions.
+ */
+
+ /*
+ * get elf descriptor just to examine the contents of an existing
+ * file
+ */
+ if ((c->obj->elf = elf_begin(c->obj->fd, ELF_C_READ, (Elf *) 0))
+ == (Elf *) 0) {
+ if (sflag)
+ (void) fprintf(stderr,
+ "File is not in executable and \
+ linking format(ELF).\n");
+ return (FAIL);
+ }
+ /* Rule out COFF, a.out and shell script files */
+ if (elf_kind(c->obj->elf) == ELF_K_COFF) {
+ if (sflag) {
+ (void) fprintf(stderr,
+ "File is not in executable \
+ and linking format(ELF) or archive.\n");
+ }
+ return (FAIL);
+ }
+ if (elf_kind(c->obj->elf) != ELF_K_AR &&
+ elf_kind(c->obj->elf) != ELF_K_ELF) {
+ if (sflag) {
+ (void) fprintf(stderr,
+ "File is not in executable and linking \
+ format(ELF) or archive.\n");
+ }
+ return (FAIL);
+ }
+ return (SUCCEED);
+}
+
+/* ========== obj_elf_hdr ================================================= */
+/*
+ * DESCRIPTION:
+ * Obtain the elf header, verify elf header information
+ */
+/* ======================================================================== */
+
+static int
+obj_elf_hdr(obj_list * c)
+{
+#if defined(_LP64)
+ Elf64_Ehdr *ptr;
+#else
+ Elf32_Ehdr *ptr;
+#endif
+
+ /*
+ * get the elf header if one is available for the ELF descriptor
+ * c->elf
+ */
+#if defined(_LP64)
+ if ((ptr = elf64_getehdr(c->obj->elf)) == (Elf64_Ehdr *) 0) {
+ if (sflag)
+ (void) fprintf(stderr,
+ "File is not in 64-bit format.\n");
+ return (FAIL);
+ }
+#else
+ if ((ptr = elf32_getehdr(c->obj->elf)) == (Elf32_Ehdr *) 0) {
+ if (sflag)
+ (void) fprintf(stderr,
+ "File is not in 32-bit format.\n");
+ return (FAIL);
+ }
+#endif
+
+ /* if there is elf header, save the pointer */
+#if defined(_LP64)
+ c->obj->ehdr = (Elf64_Ehdr *) ptr;
+#else
+ c->obj->ehdr = (Elf32_Ehdr *) ptr;
+#endif
+
+ /* e_ident[] is identification index which holds values */
+ /*
+ * we could also use elf_getident() to retrieve file identification
+ * data.
+ */
+
+ /*
+ * e_ident[EI_CLASS] identifies the file's class:
+ * ELFCLASSNONE - invalid class
+ * ELFCLASS32 - 32-bit objects
+ * ELFCLASS64 - 64-bit objects
+ */
+
+#if defined(_LP64)
+ if (ptr->e_ident[EI_CLASS] != ELFCLASS64) {
+ if (sflag)
+ (void) fprintf(stderr,
+ "File is not in 64-bit format.\n");
+ return (FAIL);
+ }
+#else
+ if (ptr->e_ident[EI_CLASS] != ELFCLASS32) {
+ if (sflag)
+ (void) fprintf(stderr,
+ "File is not in 32-bit format.\n");
+ return (FAIL);
+ }
+#endif
+ /*
+ * e_ident[EI_DATA] specifies the data encoding of the
+ * processor-specific data in the object file:
+ * ELFDATANONE - invalid data encoding
+ * ELFDATA2LSB - specifies 2's complement values, with the least
+ * significant byte occupying the lowest address
+ * ELFDATA2MSB - specifies 2's complement values, with the most
+ * significant byte occupying the lowest address
+ */
+
+ /*
+ * e_ident[EI_VERSION] specifies the ELF header version number.
+ * Currently, this value must be EV_CURRENT.
+ */
+
+ if (!(ptr->e_ident[EI_VERSION] == EV_CURRENT) &&
+ (ptr->e_version == EV_CURRENT)) {
+ if (sflag)
+ (void) fprintf(stderr,
+ "File is recorded in an \
+ incompatible ELF version.\n");
+ return (FAIL);
+ }
+ /* only interested in relocatable, shared object, or executable file */
+ switch (ptr->e_type) {
+ case ET_REL:
+ case ET_EXEC:
+ case ET_DYN:
+ break;
+ default:
+ if (sflag) {
+ (void) fprintf(stderr,
+ "File is not relocatable, ");
+ (void) fprintf(stderr,
+ "executable, or shared object.\n");
+ }
+ return (FAIL);
+ }
+
+ /*
+ * e_machine's value specifies the required architecture for an
+ * individual file
+ */
+
+#if defined(__sparcv9)
+ if (ptr->e_machine != EM_SPARCV9) {
+ if (sflag)
+ (void) fprintf(stderr,
+ "File is not for 64-bit \
+ SPARC machine architecture.\n");
+ return (FAIL);
+ }
+#elif defined(__amd64)
+ if (ptr->e_machine != EM_AMD64) {
+ if (sflag)
+ (void) fprintf(stderr,
+ "File is not for 64-bit \
+ amd64 machine architecture.\n");
+ return (FAIL);
+ }
+#elif defined(__i386)
+ if (ptr->e_machine != EM_386) {
+ if (sflag)
+ (void) fprintf(stderr,
+ "File is not for 32-bit \
+ i386 machine architecture.\n");
+ return (FAIL);
+ }
+#else
+ if (ptr->e_machine != EM_SPARC) {
+ if (sflag)
+ (void) fprintf(stderr,
+ "File is not for 32-bit \
+ SPARC machine architecture.\n");
+ return (FAIL);
+ }
+#endif
+ return (SUCCEED);
+}
+
+/* ========== obj_prog_hdr ============================================= */
+/*
+ * DESCRIPTION:
+ * For executable files and shared objects only, check if it has
+ * a program header table.
+ */
+/* ===================================================================== */
+
+static int
+obj_prog_hdr(obj_list * c)
+{
+ /*
+ * Assume: the elf header has already been read, and the file
+ * has already been determined to be
+ * executable, shared object, or relocatable
+ */
+
+ /*
+ * Program headers are meaningful only for executable and shared
+ * object files. It is an array of structures, each describing a
+ * segment or other information needs to prepare the program for
+ * execution.
+ */
+
+ /* skip if file is not executable or shared object */
+ /* e_type == ET_REL meaning Relocatable file */
+ if (c->obj->ehdr->e_type == ET_REL)
+ return (SUCCEED);
+
+ /*
+ * ehdr->e_phoff holds the program header table's file offset in
+ * bytes.
+ */
+ /* If the file has no program header table, this member holds zero. */
+ /*
+ * ehdr->e_phnum holds the number of entries in the program header
+ * table.
+ */
+ /*
+ * If a file has no program header table, e_phnum holds the value
+ * zero.
+ */
+
+ /* make sure there's a program header table */
+ if ((c->obj->ehdr->e_phoff == 0) ||
+ (c->obj->ehdr->e_phnum == 0)) {
+ if (sflag)
+ (void) fprintf(stderr,
+ "File has no program header table.\n");
+ return (FAIL);
+ }
+ return (SUCCEED);
+}
+
+/* ========== find_dynamic_sect ========================================== */
+/*
+ * DESCRIPTION:
+ * Find the dynamic section.
+ */
+/* ======================================================================= */
+
+static int
+find_dynamic_sect(obj_list * c)
+{
+#if defined(_LP64)
+ Elf64_Shdr *scurrent; /* temp 64 bit section pointer */
+#else
+ Elf32_Shdr *scurrent; /* temp 32 bit section pointer */
+#endif
+ Elf_Scn *scn; /* temp section header pointer */
+ Elf_Data *ddata; /* temp data header pointer */
+ size_t index; /* temp section header table index */
+
+ c->obj->dynnames = NULL; /* init of dynamic string table ptr */
+ c->obj->dynsect = NULL; /* init of dynamic section ptr */
+ c->obj->ddata = NULL; /* init of dynamic strtab data ptr */
+
+ /* only process executables and shared objects */
+ if (c->obj->ehdr->e_type != ET_EXEC && c->obj->ehdr->e_type != ET_DYN)
+ return (SUCCEED);
+
+ if ((c->obj->ehdr->e_shoff == 0) || (c->obj->ehdr->e_shnum == 0)) {
+ /* there are no sections */
+ return (SUCCEED);
+ }
+ /* search the section header table for dynamic section */
+
+ /* start with null section; section index = 0 */
+ scn = 0;
+
+ while ((scn = elf_nextscn(c->obj->elf, scn)) != 0) {
+ /* retrieve the section header */
+#if defined(_LP64)
+ scurrent = elf64_getshdr(scn);
+#else
+ scurrent = elf32_getshdr(scn);
+#endif
+
+ /* check for dynamic section; (i.e., .dynamic) */
+ if (scurrent->sh_type == SHT_DYNAMIC) {
+ ddata = 0;
+ if ((ddata = elf_getdata(scn, ddata)) == 0 ||
+ (ddata->d_size == 0))
+ return (SUCCEED);
+
+ /* now, we got data of dynamic section */
+ c->obj->dynsect = ddata->d_buf;
+
+ /* index to section header for dynamic string table */
+ index = scurrent->sh_link;
+ /* get scn descriptor of dynamic string table */
+ scn = elf_getscn(c->obj->elf, index);
+ /* get dynamic string table section header */
+#if defined(_LP64)
+ scurrent = elf64_getshdr(scn);
+#else
+ scurrent = elf32_getshdr(scn);
+#endif
+ /* get the dynamic string table data descriptor */
+ c->obj->ddata = elf_getdata(scn, (c->obj->ddata));
+ /* save the pointer to dynamic string table data */
+ c->obj->dynnames = c->obj->ddata->d_buf;
+ /*
+ * now, we got dynamic strtab and dynamic section
+ * information
+ */
+ break;
+ }
+ }
+ return (SUCCEED);
+}
+
+/* ========== find_symtabs ================================================ */
+/*
+ * DESCRIPTION:
+ * Find and check symbol tables for an application file
+ */
+/* ======================================================================== */
+
+static int
+find_symtabs(obj_list * c)
+{
+#if defined(_LP64)
+ Elf64_Shdr *shdr;
+#else
+ Elf32_Shdr *shdr;
+#endif
+ Elf_Scn *scn, *scn2;
+ Elf_Data *data;
+
+ c->obj->sym_tab = NULL;
+ c->obj->sym_num = 0;
+ c->obj->sym_names = NULL;
+ c->obj->dsym_tab = NULL;
+ c->obj->dsym_num = 0;
+ c->obj->dsym_names = NULL;
+ c->obj->sym_data = NULL;
+ c->obj->dsym_data = NULL;
+ scn = 0;
+
+ /*
+ * loop through the section header table looking for symbol tables.
+ * There must be one or two: .symtab and .dynsym
+ * upon finding a symbol table, save its pointer in obj_com.
+ */
+
+ /* get section descriptor */
+ while ((scn = elf_nextscn(c->obj->elf, scn)) != 0) {
+#if defined(_LP64)
+ Elf64_Sym *syms;
+#else
+ Elf32_Sym *syms;
+#endif
+ int symn;
+ char *strs;
+
+ /* point to section header */
+#if defined(_LP64)
+ shdr = elf64_getshdr(scn);
+#else
+ shdr = elf32_getshdr(scn);
+#endif
+
+ if (shdr == 0)
+ return (FAIL);
+
+ /* skip if this section is not a symbol table */
+ if ((shdr->sh_type != SHT_DYNSYM) &&
+ (shdr->sh_type != SHT_SYMTAB))
+ continue;
+
+ /* get data descriptor for the symbol table itself */
+ data = elf_getdata(scn, NULL);
+ if (data == NULL)
+ continue;
+
+ /* save pointer to symbol table */
+#if defined(_LP64)
+ syms = (Elf64_Sym *) data->d_buf;
+#else
+ syms = (Elf32_Sym *) data->d_buf;
+#endif
+
+ /*
+ * now start looking for the string table associated with
+ * this symbol table section
+ */
+
+ /* get section descriptor first */
+ scn2 = elf_getscn(c->obj->elf, shdr->sh_link);
+ if (scn2 == NULL)
+ continue;
+
+ /* get data descriptor for the string table section */
+ data = elf_getdata(scn2, NULL);
+ if (data == NULL)
+ continue;
+
+ /* save pointer to name string table */
+ strs = data->d_buf;
+ symn = shdr->sh_size / shdr->sh_entsize;
+
+ /* save information in obj_com */
+ if (shdr->sh_type == SHT_SYMTAB) {
+ c->obj->sym_tab = syms;
+ c->obj->sym_num = symn;
+ c->obj->sym_names = strs;
+ c->obj->sym_data = data;
+ } else { /* must be the dynamic linking symbol table */
+ c->obj->dsym_tab = syms;
+ c->obj->dsym_num = symn;
+ c->obj->dsym_names = strs;
+ c->obj->dsym_data = data;
+ } /* end if */
+ } /* end while */
+ return (SUCCEED);
+}
+
+/* ========== obj_app_symtab ============================================== */
+/*
+ * DESCRIPTION:
+ * Check existence of application's symbol tables.
+ */
+/* ======================================================================== */
+
+static int
+obj_app_symtab(obj_list * c)
+{
+ /* issue error if a relocatable file has no symbol table */
+ if (c->obj->sym_tab == NULL) {
+ if (c->obj->ehdr->e_type == ET_REL) {
+ if (sflag)
+ (void) fprintf(stderr,
+ "ELF error: no symbol \
+ table in object file.\n");
+ return (FAIL);
+ } else {
+ if (c->obj->dsym_tab == NULL) {
+ if (sflag) {
+ (void) fprintf(stderr,
+ "Warning: Binary is \
+ completely statically \
+ linked and stripped.\n");
+ }
+ return (FAIL);
+ }
+ if (sflag)
+ (void) fprintf(stderr,
+ "Binary is stripped.\n");
+ }
+ }
+ return (SUCCEED);
+}
+
+/* ========== obj_finis =================================================== */
+/*
+ * DESCRIPTION:
+ * It checks the c->fd and c->elf pointers. If they are not NULL,
+ * close the file descriptor and ELF descriptor.
+ */
+/* ======================================================================== */
+
+static void
+obj_finis(obj_list * c)
+{
+ obj_list *p;
+
+ if (c) {
+ while (c) {
+ if (c->obj->elf != (Elf *) 0)
+ (void) elf_end(c->obj->elf);
+ if (c->obj->fd != 0)
+ (void) close(c->obj->fd);
+ p = c;
+ c = c->next;
+ free(p->obj);
+ free(p);
+ }
+ }
+}
+
+/* ========= is_text_section ============================================== */
+/*
+ * DESCRIPTION:
+ * Scan through every section and returns TRUE(1) if the given section
+ * is ".text", otherwise, returns FALSE(0).
+ * INPUTS: shndx - section header index
+ * elf_file - ELF descriptor of the object file under test
+ * ehdr - ELF header of the object file under test
+ */
+/* ======================================================================== */
+
+static int
+is_text_section(int shndx,
+ Elf * elf_file,
+#if defined(_LP64)
+ Elf64_Ehdr * ehdr)
+#else
+ Elf32_Ehdr * ehdr)
+#endif
+{
+ char *sym_name;
+ Elf_Scn *scn = elf_getscn(elf_file, shndx);
+
+ if (scn != NULL) {
+#if defined(_LP64)
+ Elf64_Shdr *shdr;
+ shdr = elf64_getshdr(scn);
+#else
+ Elf32_Shdr *shdr;
+ shdr = elf32_getshdr(scn);
+#endif
+ sym_name = elf_strptr(elf_file,
+ ehdr->e_shstrndx,
+ shdr->sh_name);
+ if (strcmp(sym_name, ".text") == 0)
+ return (1);
+ }
+ return (0);
+}
+
+/* ========== scan_archive_symbols ======================================= */
+/*
+ * DESCRIPTION:
+ * Scan through the archive symbol tables and write them out.
+ * INPUTS: syms - pointer to application symbol table
+ * symn - number of entries in application symbol table
+ * buf - first byte of application string table
+ */
+/* ======================================================================= */
+
+static void
+scan_archive_symbols(obj_list * c,
+#if defined(_LP64)
+ Elf64_Sym * syms,
+#else
+ Elf32_Sym * syms,
+#endif
+ int symn,
+ char *buf,
+ Elf * elf_file,
+#if defined(_LP64)
+ Elf64_Ehdr * ehdr)
+#else
+ Elf32_Ehdr * ehdr)
+#endif
+{
+#if defined(_LP64)
+ Elf64_Sym *symtab_entry;
+#else
+ Elf32_Sym *symtab_entry;
+#endif
+ int i;
+ char *sym_name;
+ int sttype;
+ int stbind;
+
+ symtab_entry = syms;
+ for (i = 0; i < symn; i++, symtab_entry++) {
+ binding_bucket *binding;
+ /* look only at .text section symbols */
+ if (!is_text_section(symtab_entry->st_shndx, elf_file, ehdr))
+ continue;
+
+ /* look only at weak and global symbols */
+#if defined(_LP64)
+ stbind = ELF64_ST_BIND(symtab_entry->st_info);
+#else
+ stbind = ELF32_ST_BIND(symtab_entry->st_info);
+#endif
+ if (stbind != STB_GLOBAL) {
+ if (stbind != STB_WEAK)
+ continue;
+ }
+ /* look only at functions and objects */
+#if defined(_LP64)
+ sttype = ELF64_ST_TYPE(symtab_entry->st_info);
+#else
+ sttype = ELF32_ST_TYPE(symtab_entry->st_info);
+#endif
+ if (sttype != STT_FUNC) {
+ if (sttype != STT_OBJECT)
+ continue;
+ }
+ sym_name = buf + symtab_entry->st_name;
+ binding = (struct binding_bucket *)
+ malloc(sizeof (binding_bucket));
+ binding->sym = sym_name;
+ binding->obj = c->obj->ename;
+ binding->section = "TEXT";
+ binding->ref_lib = "<Unknown>";
+ binding->def_lib = "*DIRECT*";
+ if (stbind == STB_GLOBAL)
+ binding->stbind = "GLOB";
+ else if (stbind == STB_WEAK)
+ binding->stbind = "WEAK";
+ if (sttype == STT_FUNC)
+ binding->sttype = "FUNC";
+ else if (sttype == STT_OBJECT)
+ binding->sttype = "OBJT";
+ if (pflag)
+ profile_binding(binding);
+ else
+ store_binding(binding);
+ } /* end for */
+}
+
+/* ========== scan_symbols ================================================ */
+/*
+ * DESCRIPTION:
+ * Scan through the symbol table and write them out.
+ * INPUTS: syms - pointer to application symbol table
+ * symn - number of entries in application symbol table
+ * buf - first byte of application string table
+ */
+/* ======================================================================== */
+
+static void
+scan_symbols(obj_list * c,
+#if defined(_LP64)
+ Elf64_Sym * syms,
+#else
+ Elf32_Sym * syms,
+#endif
+ int symn,
+ char *buf)
+{
+#if defined(_LP64)
+ Elf64_Sym *symtab_entry;
+#else
+ Elf32_Sym *symtab_entry;
+#endif
+ int i;
+ char *sym_name;
+ int sttype;
+ int stbind;
+
+ symtab_entry = syms;
+ if (pflag) {
+ (void) fprintf(OUTPUT_FD,
+ "#profiling symbols in .text section of %s\n",
+ c->obj->ename);
+ output_dtneeded(dt_needed);
+ }
+ for (i = 0; i < symn; i++, symtab_entry++) {
+ binding_bucket *binding;
+ /* look only at .text section symbols */
+ if (!is_text_section(symtab_entry->st_shndx,
+ c->obj->elf,
+ c->obj->ehdr))
+ continue;
+
+ /* look only at weak and global symbols */
+#if defined(_LP64)
+ stbind = ELF64_ST_BIND(symtab_entry->st_info);
+#else
+ stbind = ELF32_ST_BIND(symtab_entry->st_info);
+#endif
+ if (stbind != STB_GLOBAL) {
+ if (stbind != STB_WEAK)
+ continue;
+ }
+ /* look only at functions and objects */
+#if defined(_LP64)
+ sttype = ELF64_ST_TYPE(symtab_entry->st_info);
+#else
+ sttype = ELF32_ST_TYPE(symtab_entry->st_info);
+#endif
+ if (sttype != STT_FUNC) {
+ if (sttype != STT_OBJECT)
+ continue;
+ }
+ sym_name = buf + symtab_entry->st_name;
+ binding = (struct binding_bucket *)
+ malloc(sizeof (binding_bucket));
+ binding->sym = sym_name;
+ binding->obj = c->obj->ename;
+ binding->section = "TEXT";
+ binding->ref_lib = "<Unknown>";
+ binding->def_lib = "*DIRECT*";
+ if (stbind == STB_GLOBAL)
+ binding->stbind = "GLOB";
+ else if (stbind == STB_WEAK)
+ binding->stbind = "WEAK";
+ if (sttype == STT_FUNC)
+ binding->sttype = "FUNC";
+ else if (sttype == STT_OBJECT)
+ binding->sttype = "OBJT";
+ if (pflag)
+ profile_binding(binding);
+ else
+ store_binding(binding);
+ } /* end for */
+}
+
+/* ========= bind_symbols ================================================= */
+/*
+ * DESCRIPTION:
+ * Scan through the dynamic symbol table and write them out.
+ * INPUTS: syms - pointer to application symbol table
+ * symn - number of entries in application symbol table
+ * buf - first byte of application string table
+ */
+/* ======================================================================== */
+
+static void
+bind_symbols(obj_list * c,
+#if defined(_LP64)
+ Elf64_Sym * syms,
+#else
+ Elf32_Sym * syms,
+#endif
+ int symn,
+ char *buf)
+{
+#if defined(_LP64)
+ Elf64_Sym *symtab_entry;
+#else
+ Elf32_Sym *symtab_entry;
+#endif
+ int i;
+ char *sym_name;
+ binding_bucket *binding;
+ int sttype;
+ int stbind;
+
+ symtab_entry = syms;
+ for (i = 0; i < symn; i++, symtab_entry++) {
+ /* look only at global symbols */
+#if defined(_LP64)
+ stbind = ELF64_ST_BIND(symtab_entry->st_info);
+#else
+ stbind = ELF32_ST_BIND(symtab_entry->st_info);
+#endif
+ if (symtab_entry->st_shndx == SHN_UNDEF)
+ continue;
+ if (symtab_entry->st_shndx == SHN_ABS)
+ continue;
+ if (stbind != STB_GLOBAL) {
+ if (stbind != STB_WEAK)
+ continue;
+ }
+ /* look only at functions and objects */
+#if defined(_LP64)
+ sttype = ELF64_ST_TYPE(symtab_entry->st_info);
+#else
+ sttype = ELF32_ST_TYPE(symtab_entry->st_info);
+#endif
+ if (sttype != STT_FUNC) {
+ if (sttype != STT_OBJECT)
+ continue;
+ }
+ sym_name = buf + symtab_entry->st_name;
+ binding = (binding_bucket *) malloc(sizeof (binding_bucket));
+ binding->obj = c->obj->ename;
+ binding->sym = sym_name;
+ if (!pflag)
+ check_store_binding(binding);
+ } /* end for */
+}
+
+/* ========== get_scnfd =================================================== */
+/*
+ * DESCRIPTION:
+ * Gets section descriptor for the associated string table
+ * and verifies that the type of the section pointed to is
+ * indeed of type STRTAB. Returns a valid section descriptor
+ * or NULL on error.
+ */
+/* ======================================================================== */
+
+static Elf_Scn *
+get_scnfd(Elf * e_file,
+ int shstrtab,
+ int SCN_TYPE)
+{
+ Elf_Scn *scn_fd;
+#if defined(_LP64)
+ Elf64_Shdr *shdr;
+#else
+ Elf32_Shdr *shdr;
+#endif
+
+ if ((scn_fd = elf_getscn(e_file, shstrtab)) == NULL)
+ return (NULL);
+
+#if defined(_LP64)
+ shdr = elf64_getshdr(scn_fd);
+#else
+ shdr = elf32_getshdr(scn_fd);
+#endif
+
+ if (shdr->sh_type != SCN_TYPE)
+ return (NULL);
+ return (scn_fd);
+}
+
+/* ========== print_symtab ================================================ */
+/*
+ * DESCRIPTION:
+ * Outputs symbol bindings from symbol table to hash table.
+ */
+/* ======================================================================== */
+
+static void
+print_symtab(obj_list * com,
+ Elf * elf_file,
+#if defined(_LP64)
+ Elf64_Ehdr * ehdr,
+ Elf64_Shdr * shdr,
+#else
+ Elf32_Ehdr * ehdr,
+ Elf32_Shdr * shdr,
+#endif
+ Elf_Scn * p_sd,
+ char *filename)
+{
+#if defined(_LP64)
+ Elf64_Sym *syms;
+#else
+ Elf32_Sym *syms;
+#endif
+ Elf_Data *data;
+ Elf_Scn *scn;
+ int count = 0;
+ char *strs, *fullname;
+ obj_list *c;
+
+ c = (obj_list *) malloc(sizeof (obj_list));
+ c->obj = (obj_com *) malloc(sizeof (obj_com));
+ fullname = (char *)malloc(strlen(com->obj->ename)
+ + strlen(filename) + 2);
+ (void *) strcpy(fullname, com->obj->ename);
+ (void *) strcat(fullname, "(");
+ (void *) strcat(fullname, filename);
+ (void *) strcat(fullname, ")");
+ c->obj->ename = fullname;
+
+ if ((data = elf_getdata(p_sd, NULL)) == NULL) {
+ if (sflag)
+ (void) fprintf(stderr,
+ "%s - No symbol table data\n",
+ c->obj->ename);
+ return;
+ }
+#if defined(_LP64)
+ syms = (Elf64_Sym *) data->d_buf;
+#else
+ syms = (Elf32_Sym *) data->d_buf;
+#endif
+
+ scn = elf_getscn(elf_file, shdr->sh_link);
+ if (scn == NULL)
+ return;
+ data = elf_getdata(scn, NULL);
+ if (data == NULL)
+ return;
+ strs = data->d_buf;
+ count = shdr->sh_size / shdr->sh_entsize;
+ if (syms == NULL) {
+ if (sflag)
+ (void) fprintf(stderr,
+ "%s: Problem reading symbol data\n",
+ c->obj->ename);
+ return;
+ }
+ c->obj->sym_tab = syms;
+ c->obj->sym_num = count;
+ c->obj->sym_names = strs;
+
+ if (aflag)
+ (void) scan_archive_symbols(c,
+ c->obj->sym_tab,
+ c->obj->sym_num,
+ c->obj->sym_names,
+ elf_file,
+ ehdr);
+ else
+ (void) bind_symbols(c,
+ c->obj->sym_tab,
+ c->obj->sym_num,
+ c->obj->sym_names);
+ free(c->obj);
+ free(c);
+}
+
+/* ========== get_symtab ================================================== */
+/*
+ * DESCRIPTION:
+ * Gets the symbol table. This function does not output the contents
+ * of the symbol table but sets up the parameters and then calls
+ * print_symtab() to output the symbol bindings.
+ */
+/* ======================================================================== */
+
+static void
+get_symtab(obj_list * c,
+ Elf * elf_file,
+#if defined(_LP64)
+ Elf64_Ehdr * ehdr,
+#else
+ Elf32_Ehdr * ehdr,
+#endif
+ char *filename)
+{
+ Elf_Scn *scn, *scnfd;
+ Elf_Data *data;
+#if defined(_LP64)
+ Elf64_Word symtabtype;
+#else
+ Elf32_Word symtabtype;
+#endif
+
+ /* get section header string table */
+ scnfd = get_scnfd(elf_file, ehdr->e_shstrndx, SHT_STRTAB);
+ if (scnfd == NULL) {
+ if (sflag)
+ (void) fprintf(stderr,
+ "%s: Could not get string table\n",
+ filename);
+ return;
+ }
+ data = elf_getdata(scnfd, NULL);
+ if (data->d_size == 0) {
+ if (sflag)
+ (void) fprintf(stderr,
+ "%s: No data in string table\n",
+ filename);
+ return;
+ }
+ symtabtype = SHT_SYMTAB;
+ scn = 0;
+ while ((scn = elf_nextscn(elf_file, scn)) != 0) {
+#if defined(_LP64)
+ Elf64_Shdr *shdr;
+ if ((shdr = elf64_getshdr(scn)) == NULL)
+#else
+ Elf32_Shdr *shdr;
+ if ((shdr = elf32_getshdr(scn)) == NULL)
+#endif
+ {
+ if (sflag)
+ (void) fprintf(stderr,
+ "%s: %s:\n",
+ filename,
+ elf_errmsg(-1));
+ return;
+ }
+ if (shdr->sh_type == symtabtype)
+ print_symtab(c, elf_file, ehdr, shdr, scn, filename);
+ } /* end while */
+}
+
+/* ========== process ===================================================== */
+/*
+ * DESCRIPTION:
+ * Gets the ELF header and, if it exists, call get_symtab() to begin
+ * processing of the file; otherwise, returns with a warning.
+ */
+/* ======================================================================== */
+
+static void
+process(obj_list * c,
+ Elf * elf_file,
+ char *filename)
+{
+#if defined(_LP64)
+ Elf64_Ehdr *ehdr;
+#else
+ Elf32_Ehdr *ehdr;
+#endif
+
+#if defined(_LP64)
+ if ((ehdr = elf64_getehdr(elf_file)) == NULL)
+#else
+ if ((ehdr = elf32_getehdr(elf_file)) == NULL)
+#endif
+ {
+ if (sflag)
+ (void) fprintf(stderr,
+ "%s: %s\n",
+ filename, elf_errmsg(-1));
+ return;
+ }
+ get_symtab(c, elf_file, ehdr, filename);
+}
+
+/* ========== process_archive ============================================= */
+/*
+ * DESCRIPTION:
+ * Processes member files of an archive. This function provides
+ * a loop through an archive equivalent the processing of each_file
+ * for individual object file.
+ */
+/* ======================================================================== */
+
+static int
+process_archive(obj_list * c)
+{
+ Elf_Arhdr *p_ar;
+ Elf *arf;
+ Elf_Cmd cmd = ELF_C_READ;
+
+ while ((arf = elf_begin(c->obj->fd, cmd, c->obj->elf)) != 0) {
+ p_ar = elf_getarhdr(arf);
+ if (p_ar == NULL) {
+ if (sflag)
+ (void) fprintf(stderr,
+ "%s: %s\n",
+ c->obj->filename, elf_errmsg(-1));
+ return (FAIL);
+ }
+ if ((int)strncmp(p_ar->ar_name, "/", 1) == 0) {
+ cmd = elf_next(arf);
+ (void) elf_end(arf);
+ continue;
+ }
+ if (elf_kind(arf) == ELF_K_ELF) {
+ process(c, arf, p_ar->ar_name);
+ } else {
+ cmd = elf_next(arf);
+ (void) elf_end(arf);
+ continue;
+ }
+ cmd = elf_next(arf);
+ (void) elf_end(arf);
+ } /* end while */
+ return (SUCCEED);
+}
+
+/* ========== add_dtneeded ================================================ */
+/*
+ * DESCRIPTION:
+ * Inserts a new node into the linked list. It is basically for
+ * generating a simple linked list of DT_NEEDED entries.
+ */
+/* ======================================================================== */
+
+static dt_list *
+add_dtneeded(dt_list * p,
+ dt_list * node)
+{
+ dt_list *head = p, *tail;
+
+ if (!head)
+ head = node;
+ else {
+ tail = head;
+ if (strcmp(tail->libname, node->libname) == 0) {
+ free(node);
+ return (head);
+ }
+ while (tail->next != NULL) {
+ tail = tail->next;
+ if (strcmp(tail->libname, node->libname) == 0) {
+ free(node);
+ return (head);
+ }
+ }
+ tail->next = node;
+ }
+ return (head);
+}
+
+/* ========== find_dtneeded =============================================== */
+/*
+ * DESCRIPTION:
+ * Find the DT_NEEDED, DT_FILTER, and DT_AUXILIARY entries, and save
+ * them to link list.
+ */
+/* ======================================================================== */
+
+static void
+find_dtneeded(obj_list * c)
+{
+#if defined(_LP64)
+ Elf64_Dyn *dcurrent; /* temp 64 bit dynamic table entry ptr */
+#else
+ Elf32_Dyn *dcurrent; /* temp 32 bit dynamic table entry ptr */
+#endif
+ dt_list *tmp_lib;
+
+ dcurrent = c->obj->dynsect;
+ if (!dcurrent)
+ return;
+
+ /*
+ * If there are any DT_NEEDED
+ * entries, add them to the dt_needed list.
+ */
+
+ while (dcurrent->d_tag != DT_NULL) {
+ if (dcurrent->d_tag == DT_NEEDED) {
+ tmp_lib = (dt_list *) malloc(sizeof (dt_list));
+ tmp_lib->libname = c->obj->dynnames +
+ dcurrent->d_un.d_val;
+ tmp_lib->d_tag = dcurrent->d_tag;
+ tmp_lib->next = NULL;
+ dt_needed = add_dtneeded(dt_needed, tmp_lib);
+ }
+ dcurrent++;
+ }
+}
+
+/* ========= obj_elfcheck ================================================= */
+/*
+ * DESCRIPTION:
+ * It checks the elf header and saves its pointer if succeeds.
+ * It checks the program header and saves its pointer if succeed.
+ * It checks the section header table and saves its pointer to
+ * section header table and section header string table if it
+ * succeeds. It finds dynsym symbol table and saves its pointer.
+ * It finds symtab and saves its pointers.
+ */
+/* ======================================================================== */
+
+static int
+obj_elfcheck(obj_list * c)
+{
+ /* open the file and ELF descriptor */
+ if (obj_init(c) == FAIL) {
+ obj_finis(c);
+ return (FAIL);
+ }
+ /* if it is an archive library */
+ if (elf_kind(c->obj->elf) == ELF_K_AR) {
+ if (process_archive(c) == SUCCEED)
+ return (SUCCEED);
+ else
+ return (FAIL);
+ }
+ /* get the ELF header information */
+ if (obj_elf_hdr(c) == FAIL) {
+ obj_finis(c);
+ return (FAIL);
+ }
+ /* get the program header for dynamic, etc. */
+ if (obj_prog_hdr(c) == FAIL) {
+ obj_finis(c);
+ return (FAIL);
+ }
+ /* find and save pointers to application symbol tables */
+ if (find_symtabs(c) == FAIL) {
+ obj_finis(c);
+ return (FAIL);
+ }
+ /* check the existence of application's symbol tables */
+ if (obj_app_symtab(c) == FAIL) {
+ obj_finis(c);
+ return (FAIL);
+ }
+ /* find and save pointers to the dynamic section */
+ if (find_dynamic_sect(c) == FAIL) {
+ obj_finis(c);
+ return (FAIL);
+ }
+ /*
+ * find the DT_NEEDED entries and save the name to dt_needed link
+ * list
+ */
+ (void) find_dtneeded(c);
+
+ return (SUCCEED);
+}
+
+/* ========= analyze_dependency ========================================== */
+/*
+ * DESCRIPTION:
+ * Read in an dependency object file and analyze it.
+ * INPUTS: dep_file - dependency object file name
+ */
+/* ======================================================================= */
+
+static int
+analyze_dependency(char *dep_file)
+{
+ obj_list *dep_obj;
+
+ if (!dep_file)
+ return (SUCCEED);
+
+ dep_obj = (obj_list *) malloc(sizeof (obj_list));
+ (void) memset(dep_obj, 0, sizeof (obj_list));
+ dep_obj->obj = (obj_com *) malloc(sizeof (obj_com));
+ (void) memset(dep_obj->obj, 0, sizeof (obj_com));
+ dep_obj->next = NULL;
+ dep_obj->obj->filename = dep_file;
+ dep_obj->obj->ename = dep_obj->obj->filename;
+
+ if (obj_elfcheck(dep_obj) == FAIL)
+ return (FAIL);
+
+ if (dep_obj->obj->dsym_names != NULL)
+ bind_symbols(dep_obj,
+ dep_obj->obj->dsym_tab,
+ dep_obj->obj->dsym_num,
+ dep_obj->obj->dsym_names);
+
+ if (dep_obj->obj->sym_names != NULL)
+ bind_symbols(dep_obj,
+ dep_obj->obj->sym_tab,
+ dep_obj->obj->sym_num,
+ dep_obj->obj->sym_names);
+ return (SUCCEED);
+}
+
+/* ========= analyze_main =============================================== */
+/*
+ * DESCRIPTION:
+ * Read in an object file and analyze it.
+ */
+/* ====================================================================== */
+
+static void
+analyze_main(obj_list * c)
+{
+ int i;
+
+ if (obj_elfcheck(c) == FAIL)
+ exit(1);
+
+ aflag = FALSE;
+
+ if (c->obj->sym_names != NULL)
+ scan_symbols(c,
+ c->obj->sym_tab,
+ c->obj->sym_num,
+ c->obj->sym_names);
+ else if (c->obj->dsym_names != NULL)
+ scan_symbols(c,
+ c->obj->dsym_tab,
+ c->obj->dsym_num,
+ c->obj->dsym_names);
+
+ if (c->obj->numfiles == 0)
+ return;
+
+ for (i = 0; i < c->obj->numfiles; i++)
+ (void) analyze_dependency(c->obj->filenames[i]);
+}
+
+/* ========= analyze_args ================================================= */
+/*
+ * DESCRIPTION:
+ * Analyze the command-line options.
+ */
+/* ======================================================================== */
+
+static int
+analyze_args(obj_list * c,
+ int argc,
+ char *argv[])
+{
+ extern char *optarg;
+ extern int optind;
+ int option;
+ int i;
+ char *nameptr;
+ char slash = '/';
+ int errflg = 0;
+
+ if ((nameptr = strrchr(argv[0], slash)) != NULL)
+ nameptr++;
+ else
+ nameptr = argv[0];
+
+ while ((option = getopt(argc, argv, "pso:a")) != EOF) {
+ switch (option) {
+ case 'p': /* just do profiling; write to stdout */
+ pflag = 1;
+ break;
+ case 's': /* silent mode to turn off stderr messages */
+ sflag = 0;
+ break;
+ case 'o': /* redirects the output */
+ outputfile = optarg;
+ oflag = 1;
+ break;
+ case 'a': /* processes archive as input */
+ aflag = 1;
+ break;
+ case '?':
+ default:
+ errflg++;
+ } /* end switch */
+ } /* end while */
+
+ /* exit if there are no files to process */
+ if (optind >= argc)
+ errflg++;
+ if (errflg) {
+ (void) fprintf(stderr,
+ "usage: %s [-p] [-s] [-o outputfile] ", nameptr);
+ (void) fprintf(stderr,
+ "<archive>|<binary_executable>\n");
+ (void) fprintf(stderr,
+ "\t\t [<archive>|<dynamic library>...]\n");
+ return (FALSE);
+ } /* end if */
+ c->obj->filename = argv[optind++];
+ c->obj->ename = c->obj->filename;
+
+ /* compute number of files and save their pointers */
+ c->obj->numfiles = argc - optind;
+
+ if (c->obj->numfiles > 0) {
+ i = 0;
+ c->obj->filenames = (char **)
+ malloc(sizeof (char *) *
+ (c->obj->numfiles + 1));
+ for (; optind < argc; i++, optind++)
+ c->obj->filenames[i] = argv[optind];
+ }
+ return (TRUE);
+}
+
+/* ======================================================================= */
+/*
+ * Here starts the main ()
+ */
+/* ======================================================================= */
+
+void
+main(int argc,
+ char **argv)
+{
+ obj_list *main_obj;
+ dt_list *q;
+
+ main_obj = (obj_list *) malloc(sizeof (obj_list));
+ (void) memset(main_obj, 0, sizeof (obj_list));
+ main_obj->obj = (obj_com *) malloc(sizeof (obj_com));
+ (void) memset(main_obj->obj, 0, sizeof (obj_com));
+ main_obj->next = NULL;
+
+ if (!analyze_args(main_obj, argc, argv))
+ exit(1);
+
+ if (oflag && pflag) {
+ if ((OUTPUT_FD = fopen(outputfile, "w")) == NULL) {
+ if (sflag)
+ (void) fprintf(stderr,
+ "\nfopen failed to open <%s>...\n\n",
+ outputfile);
+ exit(1);
+ }
+ }
+ /* generates profile report if pflag is set */
+ if (pflag)
+ (void) fprintf(OUTPUT_FD,
+ "#generated by %s\n",
+ argv[0]);
+
+ /* analyze the input file */
+ analyze_main(main_obj);
+
+ /* generates profile report */
+ if (!pflag)
+ output_binding(argv[0], main_obj->obj->ename);
+
+ /* close the library .so file descriptor and ELF descriptor */
+ obj_finis(main_obj);
+
+ /* de-allocates the dt_needed link list */
+ if (dt_needed) {
+ while (dt_needed) {
+ q = dt_needed;
+ dt_needed = dt_needed->next;
+ free(q);
+ }
+ }
+ /* close the output redirect file descriptor */
+ if (oflag)
+ (void) fclose(OUTPUT_FD);
+
+ exit(0);
+}
diff --git a/usr/src/cmd/abi/appcert/static_prof/static_prof.h b/usr/src/cmd/abi/appcert/static_prof/static_prof.h
new file mode 100644
index 0000000..62372cc
--- /dev/null
+++ b/usr/src/cmd/abi/appcert/static_prof/static_prof.h
@@ -0,0 +1,161 @@
+/*
+ * 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) 1998-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _STATIC_PROF_H
+#define _STATIC_PROF_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * include headers
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <libelf.h>
+#include <link.h>
+#include <sys/elf_SPARC.h>
+#include <sys/utsname.h>
+#include <errno.h>
+
+/*
+ * Declaration of global variables
+ */
+
+#define DEFBKTS 24997 /* 3571 nice big prime number */
+#define MASK (~(unsigned long)0<<28)
+
+/*
+ * bucket struct of hash table
+ */
+typedef struct binding_bucket
+{
+ char *sym;
+ char *ref_lib;
+ char *def_lib;
+ char *obj;
+ char *section;
+ char *sttype;
+ char *stbind;
+} binding_bucket;
+
+static binding_bucket bkts[DEFBKTS];
+
+/*
+ * data structure for linked list of DT_NEEDED entries
+ */
+typedef struct dt_list_tag
+{
+ char *libname;
+#if defined(_LP64)
+ Elf64_Sword d_tag;
+#else
+ Elf32_Sword d_tag;
+#endif
+ struct dt_list_tag *next;
+} dt_list;
+
+static dt_list *dt_needed = NULL; /* ptr to link list of dtneeded */
+
+/*
+ * struct for the binary object under test
+ */
+typedef struct obj_com
+{
+ char **filenames; /* name of application file */
+ char *filename;
+ int numfiles; /* number of applications to check */
+ /* ---Current application ELF file information--- */
+ char *ename; /* name of current ELF file */
+ int fd; /* file descriptor for current file */
+ Elf *elf; /* elf descriptor for current file */
+#if defined(_LP64)
+ Elf64_Ehdr *ehdr; /* 64 bit elf header for current file */
+ Elf64_Phdr *phdr; /* 64 bit prog header for current file */
+ Elf64_Dyn *dynsect; /* pointer to 64 bit dynamic section */
+#else
+ Elf32_Ehdr *ehdr; /* 32 bit elf header for current file */
+ Elf32_Phdr *phdr; /* 32 bit prog header for current file */
+ Elf32_Dyn *dynsect; /* ptr to 64 bit dynamic section */
+#endif
+ Elf_Data *ddata; /* ptr to dstring table data descriptor */
+ char *dynnames; /* pointer to dynamic string table */
+ /* ---ELF file symbol table information--- */
+ /* dynamic symbol table */
+#if defined(_LP64)
+ Elf64_Sym *dsym_tab;
+#else
+ Elf32_Sym *dsym_tab;
+#endif
+ Elf_Data *dsym_data;
+ int dsym_num;
+ char *dsym_names;
+ /* regular symbol table */
+#if defined(_LP64)
+ Elf64_Sym *sym_tab;
+#else
+ Elf32_Sym *sym_tab;
+#endif
+ Elf_Data *sym_data;
+ int sym_num;
+ char *sym_names;
+} obj_com;
+
+/*
+ * struct of the linked list of object files
+ */
+typedef struct obj_list_tag
+{
+ obj_com *obj;
+ struct obj_list_tag *next;
+} obj_list;
+
+static int oflag = 0; /* flag for redirecting output */
+static int pflag = 0; /* flag for profiling to stdout */
+static int sflag = 1; /* flag for silent mode */
+static int aflag = 1; /* flag for read input as archive */
+extern int errno; /* file opening error return code */
+static FILE *OUTPUT_FD = stdout; /* output fd: default as stdout */
+static char *outputfile; /* full pathname of output file */
+
+#define SUCCEED 0
+#define FAIL 1
+
+#define TRUE 1
+#define FALSE 0
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STATIC_PROF_H */
diff --git a/usr/src/cmd/abi/apptrace/amd64/Makefile b/usr/src/cmd/abi/apptrace/amd64/Makefile
new file mode 100644
index 0000000..5f319ca
--- /dev/null
+++ b/usr/src/cmd/abi/apptrace/amd64/Makefile
@@ -0,0 +1,38 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+
+.KEEP_STATE:
+
+all: $(OBJDIR) $(PICDIR) .WAIT $(APPTRACELIB) .WAIT $(INTCPTLIB)
+
+install: all $(ROOTLIBABI64) .WAIT $(ROOTLIBABILIBS64)
+
+include ../Makefile.targ
+include ../../Makefile.sub.64
diff --git a/usr/src/cmd/abi/apptracecmd/Makefile b/usr/src/cmd/abi/apptracecmd/Makefile
new file mode 100644
index 0000000..4bf032d
--- /dev/null
+++ b/usr/src/cmd/abi/apptracecmd/Makefile
@@ -0,0 +1,47 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+PROG = apptrace
+
+include ../../Makefile.cmd
+
+CFLAGS += $(CCVERBOSE)
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+install: all .WAIT $(ROOTPROG)
+
+clean:
+
+lint: lint_PROG
+
+_msg:
+
+include ../../Makefile.targ
diff --git a/usr/src/cmd/abi/apptracecmd/apptrace.c b/usr/src/cmd/abi/apptracecmd/apptrace.c
new file mode 100644
index 0000000..28157b2
--- /dev/null
+++ b/usr/src/cmd/abi/apptracecmd/apptrace.c
@@ -0,0 +1,376 @@
+/*
+ * 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"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/wait.h>
+#include <apptrace.h>
+#include <libintl.h>
+#include <locale.h>
+
+#ifdef TRUE
+#undef TRUE
+#endif
+#ifdef FALSE
+#undef FALSE
+#endif
+#define TRUE 1
+#define FALSE 0
+
+/* Various list pointers */
+static char *fromlist;
+static char *fromexcl;
+static char *tolist;
+static char *toexcl;
+
+static char *iflist;
+static char *ifexcl;
+static char *viflist;
+static char *vifexcl;
+
+/* The supported options */
+static char const *optlet = "F:fo:T:t:v:";
+/* basename(argv[0]) */
+static char const *command;
+
+/* The environment variables that'll get picked up by apptrace.so.1 */
+static char const *APPTRACE_BINDTO = "APPTRACE_BINDTO=";
+static char const *APPTRACE_BINDTO_EXCLUDE = "APPTRACE_BINDTO_EXCLUDE=";
+static char const *APPTRACE_BINDFROM = "APPTRACE_BINDFROM=";
+static char const *APPTRACE_BINDFROM_EXCLUDE = "APPTRACE_BINDFROM_EXCLUDE=";
+static char const *APPTRACE_OUTPUT = "APPTRACE_OUTPUT=";
+static char const *APPTRACE_PID = "APPTRACE_PID=";
+static char const *APPTRACE_INTERFACES = "APPTRACE_INTERFACES=";
+static char const *APPTRACE_INTERFACES_EXCLUDE = "APPTRACE_INTERFACES_EXCLUDE=";
+static char const *APPTRACE_VERBOSE = "APPTRACE_VERBOSE=";
+static char const *APPTRACE_VERBOSE_EXCLUDE = "APPTRACE_VERBOSE_EXCLUDE=";
+
+/* Some default values for the above */
+static char *LD_AUDIT = "LD_AUDIT=/usr/lib/abi/apptrace.so.1";
+#if defined(sparc) || defined(__sparcv9)
+static char *LD_AUDIT_64 =
+ "LD_AUDIT_64=/usr/lib/abi/sparcv9/apptrace.so.1";
+#elif defined(i386) || defined(__amd64)
+static char *LD_AUDIT_64 =
+ "LD_AUDIT_64=/usr/lib/abi/amd64/apptrace.so.1";
+#else
+#error Unsupported Platform
+#endif
+
+static char const *one = "1";
+
+/* The local support functions */
+static void usage(char const *);
+static void stuffenv(char const *, char const *);
+static char *buildlist(char **, char const *);
+
+int
+main(int argc, char **argv)
+{
+ int opt;
+ int fflag = FALSE;
+ int errflg = FALSE;
+ char *outfile = NULL;
+ int stat_loc;
+ pid_t wret, pid;
+
+ (void) setlocale(LC_ALL, "");
+#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
+#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
+#endif
+ (void) textdomain(TEXT_DOMAIN);
+
+
+ /* Squirrel the basename of the command name away. */
+ if ((command = strrchr(argv[0], '/')) != NULL)
+ command++;
+ else
+ command = argv[0];
+
+ while ((opt = getopt(argc, argv, optlet)) != EOF) {
+ switch (opt) {
+ case 'F':
+ if (*optarg == '!')
+ (void) buildlist(&fromexcl, optarg + 1);
+ else
+ (void) buildlist(&fromlist, optarg);
+ break;
+ case 'f':
+ fflag = TRUE;
+ break;
+ case 'o':
+ outfile = optarg;
+ break;
+ case 'T':
+ if (*optarg == '!')
+ (void) buildlist(&toexcl, optarg + 1);
+ else
+ (void) buildlist(&tolist, optarg);
+ break;
+ case 't':
+ if (*optarg == '!')
+ (void) buildlist(&ifexcl, optarg + 1);
+ else
+ (void) buildlist(&iflist, optarg);
+ break;
+ case 'v':
+ if (*optarg == '!')
+ (void) buildlist(&vifexcl, optarg + 1);
+ else
+ (void) buildlist(&viflist, optarg);
+ break;
+ default:
+ errflg = TRUE;
+ break;
+ }
+ }
+
+ /*
+ * Whack the argument vector so that the remainder will be
+ * ready for passing to exec
+ */
+ argc -= optind;
+ argv += optind;
+
+ /*
+ * If there was a problem with the options, or there was no command
+ * to be run, then give the usage message and bugout.
+ */
+ if (errflg || argc <= 0) {
+ usage(command);
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ * This is where the environment gets setup.
+ */
+ if (fflag == TRUE)
+ stuffenv(APPTRACE_PID, one);
+
+ if (fromexcl != NULL)
+ stuffenv(APPTRACE_BINDFROM_EXCLUDE, fromexcl);
+ if (fromlist != NULL)
+ stuffenv(APPTRACE_BINDFROM, fromlist);
+
+ if (tolist != NULL)
+ stuffenv(APPTRACE_BINDTO, tolist);
+ if (toexcl != NULL)
+ stuffenv(APPTRACE_BINDTO_EXCLUDE, toexcl);
+
+ if (iflist != NULL)
+ stuffenv(APPTRACE_INTERFACES, iflist);
+ if (ifexcl != NULL)
+ stuffenv(APPTRACE_INTERFACES_EXCLUDE, ifexcl);
+
+ if (viflist != NULL)
+ stuffenv(APPTRACE_VERBOSE, viflist);
+ if (vifexcl != NULL)
+ stuffenv(APPTRACE_VERBOSE_EXCLUDE, vifexcl);
+
+ if (outfile != NULL)
+ stuffenv(APPTRACE_OUTPUT, outfile);
+
+ /*
+ * It is the setting of the LD_AUDIT environment variable
+ * that tells ld.so.1 to enable link auditing when the child
+ * is exec()ed.
+ */
+ (void) putenv(LD_AUDIT);
+ (void) putenv(LD_AUDIT_64);
+
+ /*
+ * The environment is now all setup.
+ * For those about to rock, we salute you!
+ */
+ pid = fork();
+ switch (pid) {
+ /* Error */
+ case -1:
+ (void) fprintf(stderr, gettext("%s: fork failed: %s\n"),
+ command, strerror(errno));
+ exit(EXIT_FAILURE);
+ break;
+ /* Child */
+ case 0:
+ /*
+ * Usual failure is argv[0] does not exist or is
+ * not executable.
+ */
+ if (execvp(argv[0], argv)) {
+ (void) fprintf(stderr, gettext("%s: %s: %s\n"),
+ command, argv[0], strerror(errno));
+ _exit(EXIT_FAILURE);
+ }
+ break;
+ /* Parent */
+ default:
+ wret = waitpid(pid, &stat_loc, 0);
+ if (wret == -1) {
+ (void) fprintf(stderr,
+ gettext("%s: waitpid failed: %s\n"),
+ command, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ if (wret != pid) {
+ (void) fprintf(stderr,
+ gettext("%s: "
+ "waitpid returned %ld when child pid was %ld\n"),
+ command, wret, pid);
+ exit(EXIT_FAILURE);
+ }
+
+ if (WIFSIGNALED(stat_loc)) {
+ (void) fprintf(stderr, gettext("\n%s: %s: %s"),
+ command, argv[0], strsignal(WTERMSIG(stat_loc)));
+ if (WCOREDUMP(stat_loc)) {
+ (void) fputs(gettext("(Core dump)"), stderr);
+#ifdef DEBUG
+ (void) fputs(gettext("\nRunning pstack:\n"),
+ stderr);
+ (void) putenv("LD_AUDIT=");
+ (void) putenv("LD_AUDIT_64=");
+ (void) system("/usr/proc/bin/pstack core");
+#endif
+ }
+ (void) putc('\n', stderr);
+ }
+
+ /* Normal return from main() */
+ return (WEXITSTATUS(stat_loc));
+ }
+ /* NOTREACHED */
+}
+
+/*
+ * Take a string in the form "VAR=" and another in the
+ * form "value" and paste them together.
+ */
+static void
+stuffenv(char const *var, char const *val)
+{
+ int lenvar, lenval;
+ char *stuff;
+
+ lenvar = strlen(var);
+ lenval = strlen(val);
+
+ if ((stuff = malloc(lenvar + lenval + 1)) == NULL) {
+ (void) fprintf(stderr, gettext("%s: malloc failed\n"), command);
+ exit(EXIT_FAILURE);
+ }
+ (void) sprintf(stuff, "%s%s", var, val);
+ (void) putenv(stuff);
+}
+
+/*
+ * If *dst is empty, use strdup to duplicate src.
+ * Otherwise: dst = dst + "," + src;
+ */
+static char *
+buildlist(char **dst, char const *src)
+{
+ int len;
+ char *p;
+
+ /*
+ * If dst is still empty then dup,
+ * if dup succeeds set dst.
+ */
+ if (*dst == NULL) {
+ p = strdup(src);
+ if (p == NULL)
+ goto error;
+ *dst = p;
+ return (p);
+ }
+
+ len = strlen(*dst);
+
+ /* +2 because of the comma we add below */
+ if ((p = realloc(*dst, len + strlen(src) + 2)) == NULL)
+ goto error;
+
+ *dst = p;
+
+ *(*dst + len) = ',';
+ (void) strcpy((*dst + len + 1), src);
+
+ return (*dst);
+
+error:
+ (void) fprintf(stderr, gettext("%s: allocation failed: %s\n"),
+ command, strerror(errno));
+ exit(EXIT_FAILURE);
+ /* NOTREACHED */
+}
+
+static void
+usage(char const *prog)
+{
+ (void) fprintf(stderr, gettext("Usage: %s [-f][-F [!]tracefromlist]"
+ "[-T [!]tracetolist][-o outputfile]\n"
+ " [-t calls][-v calls] prog [prog arguments]\n"
+
+ " -F <bindfromlist>\n"
+ " A comma separated list of libraries that are to be\n"
+ " traced. Only calls from these libraries will be\n"
+ " traced. The default is to trace calls from the\n"
+ " main executable.\n"
+ " If <bindfromlist> begins with a ! then it defines\n"
+ " a list of libraries to exclude from the trace.\n"
+ " -T <bindtolist>\n"
+ " A comma separated list of libraries that are to be\n"
+ " traced. Only calls to these libraries will be\n"
+ " traced. The default is to trace all calls.\n"
+ " If <bindtolist> begins with a ! then it defines\n"
+ " a list of libraries to exclude from the trace.\n"
+ " -o <outputfile>\n"
+ " %s output will be directed to 'outputfile'.\n"
+ " by default it is placed on stderr\n"
+ " -f\n"
+ " Follow all children created by fork() and also\n"
+ " print apptrace output for the children. This also\n"
+ " causes a 'pid' to be added to each output line\n"
+ " -t <tracelist>\n"
+ " A comma separated list of interfaces to trace.\n"
+ " A list preceded by ! is an exlusion list.\n"
+ " -v <verboselist>\n"
+ " A comman separated list of interfaces to trace\n"
+ " verbosely.\n"
+ " A list preceded by ! is an exclusion list.\n"
+ " Interfaces matched in -v do not also need to be\n"
+ " named by -t\n"
+ " All lists may use shell style wild cards.\n"
+ " Leading path components or suffixes are not required when\n"
+ " listing libraries (ie. libc will match /usr/lib/libc.so.1).\n"),
+ prog, prog);
+}
diff --git a/usr/src/cmd/abi/common/stab.h b/usr/src/cmd/abi/common/stab.h
new file mode 100644
index 0000000..65a5bf8
--- /dev/null
+++ b/usr/src/cmd/abi/common/stab.h
@@ -0,0 +1,230 @@
+/*
+ * 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 FILE IS NOW THE MASTER stab.h FILE, A DUPLICATE OF stab.h MAY BE
+ * MAINTAINED BY SPARCompilers
+ *
+ * KEEP IN SYNC
+ *
+ */
+
+/* FILE NOT I18N */
+
+/*
+ * This file gives definitions supplementing <a.out.h>
+ * for debugging symbol table entries.
+ * These entries must have one of the N_STAB bits on,
+ * and are subject to relocation according to the masks in <a.out.h>
+ * on 4.x (stabs not relocated on SVR4).
+ */
+
+#ifndef _STAB_H
+#define _STAB_H
+
+#if (!defined(_a_out_h) && !defined(_A_OUT_H)) || defined(HP_UX)
+/* this file also contains fragments of a.out.h relevant to
+ * support of stab processing within ELF files
+ * (when a.out.h is not available)
+ */
+struct stab {
+ unsigned n_strx; /* index into file string table */
+ unsigned char n_type; /* type flag (N_TEXT,..) */
+ char n_other; /* used by N_SLINE stab */
+ short n_desc; /* see stabs documentation */
+ unsigned n_value; /* value of symbol (or sdb offset) */
+};
+
+/* patchtypes for N_PATCH stab (n_desc field) */
+
+#define P_BITFIELD 0x1
+#define P_SPILL 0x2
+#define P_SCOPY 0x3
+
+/* markers for N_CODETAG stab (n_other field) */
+
+#define CODETAG_BITFIELD 0x1 /* load/store of a bit field */
+#define CODETAG_SPILL 0x2 /* spill of registers */
+#define CODETAG_SCOPY 0x3 /* structure copy load/store */
+#define CODETAG_FSTART 0x4 /* points to first inst of new frame (0==leaf)*/
+#define CODETAG_END_CTORS 0x5 /* end of calls to super-class constructors */
+/* UNUSED 0x6 DW_ATCF_SUN_branch_target in dwarf, not used in stabs */
+#define CODETAG_STACK_PROBE 0x7 /* marks insns which probe the stack memory */
+
+/*
+ * Simple values for n_type.
+ */
+#define N_UNDF 0x0 /* undefined */
+#define N_ABS 0x2 /* absolute */
+#define N_TEXT 0x4 /* text */
+#define N_DATA 0x6 /* data */
+#define N_BSS 0x8 /* bss */
+#define N_COMM 0x12 /* common (internal to ld) */
+#define N_FN 0x1f /* file name symbol */
+
+#define N_EXT 01 /* external bit, or'ed in */
+#define N_TYPE 0x1e /* mask for all the type bits */
+
+#endif
+
+/*
+ * maximum length of stab string before using continuation stab.
+ * (this is just a suggested limit), assembler has no limit.
+ */
+
+#define MAX_STAB_STR_LEN 250
+
+/*
+ * for symbolic debuggers:
+ */
+#define N_GSYM 0x20 /* global symbol: name,,0,type,0 */
+#define N_FNAME 0x22 /* procedure name (f77 kludge): name,,0 */
+#define N_FUN 0x24 /* procedure: name,,0,linenumber,0 */
+#define N_OUTL 0x25 /* outlined func: name,,0,linenumber,0 */
+#define N_STSYM 0x26 /* static symbol: name,,0,type,0 or section relative */
+#define N_TSTSYM 0x27 /* thread static symbol: Ttdata.data */
+#define N_LCSYM 0x28 /* .lcomm symbol: name,,0,type,0 or section relative */
+#define N_TLCSYM 0x29 /* thread local symbol: Ttbss.bss */
+#define N_MAIN 0x2a /* name of main routine : name,,0,0,0 */
+#define N_ROSYM 0x2c /* ro_data: name,,0,type,0 or section relative */
+#define N_FLSYM 0x2e /* fragmented data: name,,0,type,0 */
+#define N_TFLSYM 0x2f /* thread fragmented data: name,,0,type,0 */
+#define N_PC 0x30 /* global pascal symbol: name,,0,subtype,line */
+#define N_CMDLINE 0x34 /* command line info */
+#define N_OBJ 0x38 /* object file path or name */
+#define N_OPT 0x3c /* compiler options */
+#define N_RSYM 0x40 /* register sym: name,,0,type,register */
+#define N_SLINE 0x44 /* src line: 0,,0,linenumber,function relative */
+#define N_XLINE 0x45 /* h.o. src line: 0,,0,linenumber>>16,0 */
+#define N_ILDPAD 0x4c /* now used as ild pad stab value=strtab delta
+ was designed for "function start.end" */
+#define N_SSYM 0x60 /* structure elt: name,,0,type,struct_offset */
+#define N_ENDM 0x62 /* last stab emitted for object module */
+#define N_SO 0x64 /* source file name: name,,0,0,0 */
+#define N_MOD 0x66 /* f90 module: name,,0,0,0 */
+#define N_EMOD 0x68 /* end of f90 module: name,,0,0,0 */
+#define N_READ_MOD 0x6a /* use of f90 module: name;locallist,,0,0,0 */
+#define N_ALIAS 0x6c /* alias name: name,,0,0,0 */
+#define N_LSYM 0x80 /* local sym: name,,0,type,offset */
+#define N_BINCL 0x82 /* header file: name,,0,0,0 */
+#define N_SOL 0x84 /* #included file name: name,,0,0,0 */
+#define N_PSYM 0xa0 /* parameter: name,,0,type,offset */
+#define N_EINCL 0xa2 /* end of include file */
+#define N_ENTRY 0xa4 /* alternate entry: name,linenumber,0 */
+#define N_SINCL 0xa6 /* shared include file */
+#define N_LBRAC 0xc0 /* left bracket: 0,,0,nesting level,function relative */
+#define N_EXCL 0xc2 /* excluded include file */
+#define N_USING 0xc4 /* C++ using command */
+#define N_ISYM 0xc6 /* position independent type symbol, internal */
+#define N_ESYM 0xc8 /* position independent type symbol, external */
+#define N_PATCH 0xd0 /* Instruction to be ignored by run-time checking. */
+#define N_CONSTRUCT 0xd2 /* C++ constructor call. */
+#define N_DESTRUCT 0xd4 /* C++ destructor call. */
+#define N_CODETAG 0xd8 /* Generic code tag */
+#define N_FUN_CHILD 0xd9 /* Identifies a child function */
+#define N_RBRAC 0xe0 /* right bracket: 0,,0,nesting level,function relative */
+#define N_BCOMM 0xe2 /* begin common: name,, */
+#define N_TCOMM 0xe3 /* begin task common: name,, */
+#define N_ECOMM 0xe4 /* end task_common/common: name,, */
+#define N_XCOMM 0xe6 /* excluded common block */
+#define N_ECOML 0xe8 /* end common (local name): ,,address */
+#define N_WITH 0xea /* pascal with statement: type,,0,0,offset */
+#define N_LENG 0xfe /* second stab entry with length information */
+
+/*
+ * for analyzer (cache profile feedback support)
+ */
+#define N_CPROF 0xf0 /* annotation for cache profile feedback */
+
+/*
+ * n_descr values used in N_CPROF stabs. The n_descr field of
+ * an N_CPROF stab identifies the type of table whose location
+ * is defined by the N_CPROF stab.
+ */
+typedef enum n_cprof_instr_type_t {
+ N_CPROF_INSTR_TYPE_LOAD=0, /* profiled load ops */
+ N_CPROF_INSTR_TYPE_STORE, /* profiled store ops */
+ N_CPROF_INSTR_TYPE_PREFETCH, /* profiled prefetch ops */
+ N_CPROF_INSTR_TYPE_BRTARGET, /* branch target locations */
+ N_CPROF_INSTR_TYPE_NTYPES /* number of types */
+} n_cprof_instr_type_t;
+
+/*
+ * for code browser only
+ */
+#define N_BROWS 0x48 /* path to associated .cb file */
+
+/*
+ * for functions -- n_other bits for N_FUN stab
+ */
+#define N_FUN_PURE (1<<0)
+#define N_FUN_ELEMENTAL (1<<1)
+#define N_FUN_RECURSIVE (1<<2)
+
+/*
+ * for variables -- n_other bits for N_LSYM, N_GSYM, N_LCSYM, N_STSYM, ...
+ */
+#define N_SYM_OMP_TLS (1<<3)
+
+/*
+ * Optional language designations for N_SO (n_desc field)
+ */
+#define N_SO_AS 1 /* Assembler */
+#define N_SO_C 2 /* C */
+#define N_SO_ANSI_C 3 /* ANSI C */
+#define N_SO_CC 4 /* C++ */
+#define N_SO_FORTRAN 5 /* Fortran 77 */
+#define N_SO_FORTRAN77 5 /* Fortran 77 */
+#define N_SO_PASCAL 6 /* Pascal */
+#define N_SO_FORTRAN90 7 /* Fortran 90 */
+#define N_SO_JAVA 8 /* Java */
+#define N_SO_C99 9 /* C99 */
+
+/*
+ * Floating point type values (encoded in "R" type specification string)
+ */
+#define NF_NONE 0 /* Undefined type */
+#define NF_SINGLE 1 /* Float IEEE 32 bit floating point */
+#define NF_DOUBLE 2 /* Double IEEE 64 bit floating point */
+#define NF_COMPLEX 3 /* Complex (2 32bit floats) */
+#define NF_COMPLEX16 4 /* Complex (2 64bit doubles) */
+#define NF_COMPLEX32 5 /* Complex (2 128bit long doubles) */
+#define NF_LDOUBLE 6 /* Long double 128 bit floating point */
+#define NF_INTERARITH 7 /* Interval (2 32bit floats) */
+#define NF_DINTERARITH 8 /* Interval (2 64bit doubles) */
+#define NF_QINTERARITH 9 /* Interval (2 128bit long doubles) */
+#define NF_IMAGINARY 10 /* Imaginary (1 32bit floats) */
+#define NF_DIMAGINARY 11 /* Imaginary (1 64bit doubles) */
+#define NF_QIMAGINARY 12 /* Imaginary (1 128bit long doubles) */
+
+#endif
+
+
diff --git a/usr/src/cmd/abi/libstabspf/amd64/Makefile b/usr/src/cmd/abi/libstabspf/amd64/Makefile
new file mode 100644
index 0000000..62e90b4
--- /dev/null
+++ b/usr/src/cmd/abi/libstabspf/amd64/Makefile
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+MAPDIR= ../spec/amd64
+include ../Makefile.lib
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.lib.64
+include ../Makefile.com
+
+LINTFLAGS64 += -Xarch=amd64 -sF -errtags=yes -erroff=E_BAD_PTR_CAST_ALIGN
+
+install: all $(ROOTABILIB64)
diff --git a/usr/src/cmd/abi/libstabspf/spec/amd64/Makefile b/usr/src/cmd/abi/libstabspf/spec/amd64/Makefile
new file mode 100644
index 0000000..f2aa355
--- /dev/null
+++ b/usr/src/cmd/abi/libstabspf/spec/amd64/Makefile
@@ -0,0 +1,46 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# cmd/abi/libstabspf/spec/amd64/Makefile
+#
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.lib.64
+
+# Uncomment the following if the linker complains
+#amd64_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+install: $(SPECMAP)
diff --git a/usr/src/cmd/abi/req.flg b/usr/src/cmd/abi/req.flg
new file mode 100644
index 0000000..078b503
--- /dev/null
+++ b/usr/src/cmd/abi/req.flg
@@ -0,0 +1,31 @@
+#!/bin/sh
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+echo_file usr/src/lib/Makefile.lib
+echo_file usr/src/lib/Makefile.targ
diff --git a/usr/src/cmd/abi/spectrans/Makefile b/usr/src/cmd/abi/spectrans/Makefile
new file mode 100644
index 0000000..8b8dd4d
--- /dev/null
+++ b/usr/src/cmd/abi/spectrans/Makefile
@@ -0,0 +1,47 @@
+#
+# 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
+#
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright 1996,1998-1999,2002 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# cmd/abi/spectrans/Makefile
+
+.KEEP_STATE:
+
+SUBDIRS = parser spec2map spec2trace
+
+all := TARGET= all
+install := TARGET= install
+clean := TARGET= clean
+clobber := TARGET= clobber
+lint := TARGET= lint
+
+all install clean clobber lint: $(SUBDIRS)
+
+_msg: # No messages for these tools
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
diff --git a/usr/src/cmd/abi/spectrans/Makefile.arch b/usr/src/cmd/abi/spectrans/Makefile.arch
new file mode 100644
index 0000000..0edfcf6
--- /dev/null
+++ b/usr/src/cmd/abi/spectrans/Makefile.arch
@@ -0,0 +1,49 @@
+#
+# 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
+#
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1998-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# cmd/abi/daa2x/Makefile.arch
+
+i386_ARCHITECTURES = i386
+sparc_ARCHITECTURES = sparc
+ALL_ARCHITECTURES = $(i386_ARCHITECTURES) \
+ $(sparc_ARCHITECTURES)
+
+all := TARGET= all
+install := TARGET= install
+clean := TARGET= clean
+clobber := TARGET= clobber
+lint := TARGET= lint
+
+.KEEP_STATE:
+
+all install clean clobber lint: $($(MACH)_ARCHITECTURES)
+
+$($(MACH)_ARCHITECTURES): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
diff --git a/usr/src/cmd/abi/spectrans/Makefile.cmd b/usr/src/cmd/abi/spectrans/Makefile.cmd
new file mode 100644
index 0000000..6147572
--- /dev/null
+++ b/usr/src/cmd/abi/spectrans/Makefile.cmd
@@ -0,0 +1,83 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include $(SRC)/cmd/Makefile.cmd
+include ../../../Makefile.abi
+
+PROG_BIN = $(ROOTLIB)/abi/$(PROG)
+.PRECIOUS: $(PROG)
+
+U_LIB = parse
+U_BASE = ../../parser
+U_DIR = $(U_BASE)/$(MACH)
+U_LIB_A = $(U_DIR)/lib$(U_LIB).a
+
+CFLAGS += $(CCVERBOSE)
+CPPFLAGS += -I$(U_BASE) -I..
+LDFLAGS += -L$(U_DIR)
+LINTFLAGS += -xsuF -errtags=yes
+
+LDLIBS += -l$(U_LIB) -lgen
+LINTLIBS = -L$(U_DIR) -l$(U_LIB)
+
+SRCS = $(OBJECTS:%.o=../%.c)
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+%.o: ../%.y
+ $(YACC.y) $<
+ $(COMPILE.c) -o $@ y.tab.c
+ $(RM) y.tab.c
+
+%.o: ../%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+$(PROG): $(U_LIB_A) $(OBJECTS) $(YACC_OBJS)
+ $(LINK.c) -o $@ $(OBJECTS) $(YACC_OBJS) $(LDLIBS)
+ $(POST_PROCESS)
+
+$(U_LIB_A):
+ @cd $(U_DIR); pwd; $(MAKE) all
+
+install: $(PROG_BIN)
+
+$(PROG_BIN) := FILEMODE = 755
+$(PROG_BIN): $(PROG)
+ $(INS.file) $(PROG)
+
+clean:
+ -$(RM) $(OBJECTS) $(YACC_OBJS)
+
+clobber: clean
+ -$(RM) $(PROG) $(CLOBBERFILES)
+
+lint:
+ $(LINT.c) $(SRCS) $(LINTLIBS)
diff --git a/usr/src/cmd/abi/spectrans/parser/Makefile b/usr/src/cmd/abi/spectrans/parser/Makefile
new file mode 100644
index 0000000..0f98d16
--- /dev/null
+++ b/usr/src/cmd/abi/spectrans/parser/Makefile
@@ -0,0 +1,32 @@
+#
+# 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
+#
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1998-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# cmd/abi/spectrans/lib/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.arch
diff --git a/usr/src/cmd/abi/spectrans/parser/Makefile.targ b/usr/src/cmd/abi/spectrans/parser/Makefile.targ
new file mode 100644
index 0000000..c00da55
--- /dev/null
+++ b/usr/src/cmd/abi/spectrans/parser/Makefile.targ
@@ -0,0 +1,56 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# cmd/abi/spectrans/util/Makefile.targ
+#
+
+.KEEP_STATE:
+
+LIBRARY = libparse.a
+
+OBJECTS = errlog.o \
+ extends.o \
+ frontend.o \
+ main.o
+
+include $(SRC)/lib/Makefile.lib
+
+SRCS = $(OBJECTS:%.o=../%.c)
+
+LINTFLAGS += -xsuF -errtags=yes
+CLEANFILES += $(LINTOUT)
+CLOBBERFILES += $(LINTLIB)
+
+objs/%.o: ../%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+all install: $(LIBRARY)
+
+lint: lintcheck
+
+include $(SRC)/lib/Makefile.targ
diff --git a/usr/src/cmd/abi/spectrans/parser/errlog.c b/usr/src/cmd/abi/spectrans/parser/errlog.c
new file mode 100644
index 0000000..25c1f14
--- /dev/null
+++ b/usr/src/cmd/abi/spectrans/parser/errlog.c
@@ -0,0 +1,139 @@
+/*
+ * 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"
+
+/*
+ * errlog -- error logging facility for application programs
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include "errlog.h"
+
+/* Statics (this object is not threadable). */
+static int Severity;
+static struct location {
+ char *l_file;
+ int l_lineno;
+ char *l_tag;
+ char *l_line;
+} Location;
+
+/* Indentation */
+static int Trace_indent;
+/* XXX YES, its 80 spaces !@#$%^ */
+static char Trace_padding[] =
+ " "
+ " ";
+
+#define INDENT &Trace_padding[80-(Trace_indent*4)]
+#define PRINTHDR INPUT
+
+/*
+ * errlog -- simulate the syslog printf-like interface, but
+ * with a first argument oriented toward reporting
+ * application errors.
+ */
+/*VARARGS2*/
+void
+errlog(const int descriptor, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ if ((Severity < (descriptor & FATAL)) &&
+ ((descriptor & FATAL) != FATAL)) {
+ /* We don't need to say/do anything. */
+ return;
+ }
+
+ /* Produce the message. */
+ (void) fflush(stdout); /* Synchronize streams. */
+ if ((descriptor & PRINTHDR) != 0) {
+ if (Location.l_file == NULL) {
+ (void) fprintf(stderr, "programmer error, logerr "
+ "told to print file, line number, "
+ "but file was not set.\n");
+ } else {
+ (void) fprintf(stderr, "\"%s\", line %d: ",
+ Location.l_file, Location.l_lineno);
+ }
+ }
+
+ /* Indent/outdent. */
+ if (descriptor & INDENTED) {
+ (void) fprintf(stderr, "%s", INDENT);
+ Trace_indent = (Trace_indent < 20)? Trace_indent + 1: 20;
+ } else if (descriptor & OUTDENTED) {
+ Trace_indent = (Trace_indent > 0)? Trace_indent - 1: 0;
+ (void) fprintf(stderr, "%s", INDENT);
+ } else {
+ (void) fprintf(stderr, "%s", INDENT);
+ }
+
+ /* Print the stuff we did all this for. */
+ (void) vfprintf(stderr, format, ap);
+
+ if ((descriptor & INPUT) && Location.l_line != NULL) {
+ /* Emit trailers. Formatting TBD. */
+ (void) putc('\n', stderr);
+ (void) fprintf(stderr, "\tLine was: %s %s",
+ Location.l_tag, Location.l_line);
+ }
+ (void) putc('\n', stderr);
+ (void) fflush(stderr); /* No-op on Solaris. */
+
+ if ((descriptor & FATAL) == FATAL) {
+ /* Say goodbye! */
+ exit(1);
+ }
+ va_end(ap);
+}
+
+/*
+ * seterrline -- tell errlog what the context of the error is.
+ */
+void
+seterrline(const int lineno, const char *file,
+ const char *tag, const char *line)
+{
+ Location.l_lineno = lineno;
+ Location.l_file = (char *)file;
+ Location.l_tag = (char *)tag;
+ Location.l_line = (char *)line;
+}
+
+/*
+ * seterrseverity -- set the severity/loudness variable.
+ * This is traditionally the ``Verbosity'' level.
+ */
+void
+seterrseverity(const int loudness)
+{
+ Severity = (loudness & FATAL);
+}
diff --git a/usr/src/cmd/abi/spectrans/parser/errlog.h b/usr/src/cmd/abi/spectrans/parser/errlog.h
new file mode 100644
index 0000000..0415093
--- /dev/null
+++ b/usr/src/cmd/abi/spectrans/parser/errlog.h
@@ -0,0 +1,91 @@
+/*
+ * 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) 1997-1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _ERRLOG_H
+#define _ERRLOG_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * errlog -- error logging facility for application programs
+ *
+ */
+
+extern void errlog(const int, const char *, ...);
+extern void seterrline(const int, const char *, const char *, const char *);
+extern void seterrseverity(const int);
+extern void openerrlog(const char *, const int, const int);
+extern void closeerrlog(void);
+
+/*
+ * The first (non-short) int of errlog really describes a packed
+ * form of three extensible enumerations, similar to:
+ * typedef struct severity {
+ * int descriptor: 8; OTHER=0, INPUT or PROGRAM.
+ * int attributes: 8; NONE=0, INDENTED, OUTDENTED, etc.
+ * int severity: 16; FATAL (_ERROR)=-1, (RECOVERABLE_) ERROR=0
+ * WARNING, TRACING, VERBOSE (_TRACING), etc.
+ * } severity_t;
+ */
+
+#define FATAL 0x00FF
+#define ERROR 0
+
+#define WARNING 1
+#define STATUS 2
+#define TRACING 3
+#define VERBOSE 4
+
+#define INPUT (1 << 8)
+#define PROGRAM (2 << 8)
+#define OTHER 0
+
+/* Reserved for implementor. */
+#define INDENTED (1 << 16)
+#define OUTDENTED (2 << 16)
+#define BEGIN (OTHER | TRACING | INDENTED)
+#define END (OTHER | TRACING | OUTDENTED)
+
+#ifndef assert
+/* EXPERIMENTAL assert replacement, deliberately not source-compatable */
+#define assert(cond, string) \
+ if (!(cond)) { \
+ seterrline(__LINE__, __FILE__, NULL, NULL); \
+ errlog(FATAL|PROGRAM, string); \
+ }
+#else
+#error "assert.h and errlog.h both define assert: choose only one"
+#endif /* assert */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ERRLOG_H */
diff --git a/usr/src/cmd/abi/spectrans/parser/extends.c b/usr/src/cmd/abi/spectrans/parser/extends.c
new file mode 100644
index 0000000..d74dbdd
--- /dev/null
+++ b/usr/src/cmd/abi/spectrans/parser/extends.c
@@ -0,0 +1,394 @@
+/*
+ * 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) 1997-1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <libgen.h>
+#include <errno.h>
+#include "parser.h"
+#include "errlog.h"
+
+static int find_fun(char *key, char *value, char *parentfun);
+
+/*
+ * handles the extends clause of the 'function' keyword
+ * Returns the number of errors encountered
+ * This function is recursive.
+ */
+int
+do_extends(const Meta_info parentM, const Translator_info *T_info, char *value)
+{
+ static int extends_count = 0;
+ char funname[BUFSIZ], filename[MAXPATHLEN], parentfun[BUFSIZ],
+ buf[BUFSIZ], key[20];
+ char *ifilename, *f, *p;
+ char *localvalue = NULL, *buf2 = NULL;
+ FILE *efp;
+ Meta_info M;
+ int found = 0, errors = 0, ki = 0;
+ int retval;
+ int scan;
+
+ ++extends_count;
+
+ if (extends_count > MAX_EXTENDS) {
+ errlog(ERROR, "\"%s\", line %d: Error: Too many levels of "
+ "extends\n", parentM.mi_filename, parentM.mi_line_number);
+ ++errors;
+ goto ret;
+ }
+
+ scan = sscanf(value, "%s %s %s %s", funname, buf, filename, parentfun);
+ switch (scan) {
+ case 0: /* funname not set */
+ case 1: /* buf not set, though ignored */
+ case 2: /* filename not set */
+ errlog(ERROR, "\"%s\", line %d: Error: Couldn't parse "
+ "'data' or 'function' line\n",
+ parentM.mi_filename, parentM.mi_line_number);
+ ++errors;
+ goto ret;
+ break;
+ case 3:
+ (void) strncpy(parentfun, funname, BUFSIZ);
+ parentfun[BUFSIZ-1] = '\0';
+ break;
+ default:
+ break;
+ }
+
+ /* All info is from parent file - extends */
+ M.mi_ext_cnt = extends_count;
+
+ if (T_info->ti_verbosity >= TRACING) {
+ errlog(TRACING, "Extending file %s\nExtending function %s\n"
+ "SPEC's from %s\n", filename, parentfun,
+ T_info->ti_dash_I);
+ }
+
+ f = pathfind(T_info->ti_dash_I, filename, "f");
+ if (f == NULL) {
+ errlog(ERROR, "\"%s\", line %d: Error: Unable to find spec "
+ "file \"%s\"\n", parentM.mi_filename,
+ parentM.mi_line_number, filename);
+ ++errors;
+ goto ret;
+ }
+ ifilename = strdup(f);
+ if (ifilename == NULL) {
+ errlog(ERROR | FATAL, "Error: strdup() of filename failed\n");
+ }
+ efp = fopen(ifilename, "r");
+ if (efp == NULL) {
+ errlog(ERROR, "\"%s\", line %d: Error: Unable to open "
+ "file \"%s\"\n", parentM.mi_filename,
+ parentM.mi_line_number, ifilename);
+ free(ifilename);
+ ++errors;
+ goto ret;
+ }
+
+ (void) strncpy(M.mi_filename, ifilename, MAXPATHLEN);
+ M.mi_line_number = 0;
+
+ /* search for begin function */
+ while (M.mi_nlines = readline(&buf2, efp)) {
+ M.mi_line_number += M.mi_nlines;
+
+ if (!non_empty(buf2)) { /* is line non empty */
+ free(buf2);
+ buf2 = NULL;
+ continue;
+ }
+ p = realloc(localvalue, sizeof (char)*(strlen(buf2)+1));
+ if (p == NULL) {
+ errlog(ERROR | FATAL, "Error (do_extends): "
+ "Unable to allocate memory\n");
+ }
+ localvalue = p;
+ split(buf2, key, localvalue);
+ if ((found = find_fun(key, localvalue, parentfun))) {
+ /* check if architecture matches */
+ if (found = arch_match(efp, T_info->ti_archtoken))
+ break;
+ }
+ free(buf2);
+ buf2 = NULL;
+ }
+
+ if (found) {
+ int extends_err = 0;
+ static int extends_warn = 0;
+ extends_err = check4extends(ifilename, localvalue,
+ T_info->ti_archtoken, efp);
+ switch (extends_err) {
+ case -1: /* Error */
+ errlog(ERROR, "\"%s\", line %d: Error occurred while "
+ "checking for extends clause\n",
+ M.mi_filename, M.mi_line_number);
+ ++errors;
+ /*FALLTHRU*/
+ case 0: /* No Extends */
+ break;
+ case 1: /* Extends */
+ /*
+ * Warning on more then one level of extends
+ * but only warn once.
+ */
+ if (extends_count == 1) {
+ extends_warn = 1;
+ }
+ if ((extends_err = do_extends(M, T_info, localvalue))
+ != 0) {
+ if (extends_count == 1) {
+ errlog(ERROR, "\"%s\", line %d: "
+ "Error occurred while "
+ "processing 'extends'\n",
+ parentM.mi_filename,
+ parentM.mi_line_number);
+ }
+ errors += extends_err;
+ }
+ if (extends_warn == 1 && extends_count == 1) {
+ errlog(ERROR, "\"%s\", line %d: "
+ "Warning: \"%s\" does not extend "
+ "a base specification",
+ parentM.mi_filename,
+ parentM.mi_line_number,
+ funname);
+ }
+ break;
+ default: /* Programmer Error */
+ errlog(ERROR | FATAL,
+ "Error: invalid return from "
+ "check4extends: %d\n", extends_err);
+ }
+
+ free(buf2);
+ buf2 = NULL;
+
+ while (M.mi_nlines = readline(&buf2, efp)) {
+ M.mi_line_number += M.mi_nlines;
+
+ if (!non_empty(buf2)) { /* is line non empty */
+ free(buf2);
+ buf2 = NULL;
+ continue;
+ }
+ p = realloc(localvalue, sizeof (char)*(strlen(buf2)+1));
+ if (p == NULL) {
+ p = realloc(NULL,
+ sizeof (char)*(strlen(buf2)+1));
+ if (p == NULL) {
+ errlog(ERROR | FATAL,
+ "Error: unable to "
+ "allocate memory\n");
+ }
+ }
+ localvalue = p;
+ split(buf2, key, localvalue);
+ ki = interesting_keyword(keywordlist, key);
+ switch (ki) {
+ case XLATOR_KW_END:
+ goto end;
+ break;
+ case XLATOR_KW_FUNC:
+ case XLATOR_KW_DATA:
+ errlog(ERROR, "\"%s\", line %d: "
+ "Error: Interface is missing \"end\"\n"
+ "\"%s\", line %d: Error while processing "
+ "%s\n", M.mi_filename, M.mi_line_number,
+ parentM.mi_filename,
+ parentM.mi_line_number, ifilename);
+ ++errors;
+ goto end;
+ break;
+ case XLATOR_KW_NOTFOUND:
+ if (T_info->ti_verbosity >= TRACING)
+ errlog(STATUS,
+ "uninteresting keyword: %s\n", key);
+ break;
+ default:
+ retval = xlator_take_kvpair(M, ki, localvalue);
+ if (retval) {
+ if (T_info->ti_verbosity >= STATUS)
+ errlog(STATUS,
+ "Error in "
+ "xlator_take_kvpair\n");
+ ++errors;
+ }
+ }
+ free(buf2);
+ buf2 = NULL;
+ }
+ } else {
+ errlog(ERROR, "\"%s\", line %d: Error: Unable to find "
+ "function %s in %s\n", parentM.mi_filename,
+ parentM.mi_line_number, parentfun, ifilename);
+ ++errors;
+ }
+end:
+ (void) fclose(efp);
+ free(localvalue);
+ free(ifilename);
+ free(buf2);
+ret:
+ extends_count--;
+ return (errors);
+}
+
+/*
+ * find_fun()
+ * given a key value pair, and the name of the function you are
+ * searching for in the SPEC source file, this function returns 1
+ * if the beginning of the function in the SPEC source file is found.
+ * returns 0 otherwise.
+ */
+static int
+find_fun(char *key, char *value, char *parentfun)
+{
+ char pfun[BUFSIZ];
+
+ if (strcasecmp(key, "function") != 0 &&
+ strcasecmp(key, "data") != 0) {
+ return (0);
+ }
+
+ (void) sscanf(value, "%1023s", pfun);
+
+ if (strcmp(pfun, parentfun) == 0) {
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
+ * arch_match(FILE *fp, int arch)
+ * This function takes a FILE pointer, and an architecture token
+ * The FILE pointer is assumed to point at the beginning of a Function
+ * or Data specification (specifically at the first line of spec AFTER
+ * the Function or Data line)
+ * It reads all the way to the "End" line.
+ * If it finds an "arch" keyword along the way, it is checked to see if
+ * it matches the architecture currently being generated and returns
+ * 1 if a match is found. If a match is not found, it returns a
+ * 0. If no "arch" keyword is found, it returns 1.
+ *
+ * XXX - the algorithm in arch_match is very inefficient. it read through
+ * the file to find "arch" and rewinds before returning.
+ * Later all the data that was skipped while searching for "arch" may
+ * be needed and it is re-read from the disk. It would be nice to just
+ * read the data once.
+ */
+int
+arch_match(FILE *fp, int arch)
+{
+ off_t offset;
+ char key[20], buf[BUFSIZ], *buf2 = NULL, *localvalue = NULL, *p;
+ int len;
+ int has_arch = 0;
+ int archset = 0;
+
+ offset = ftello(fp);
+ if (offset == -1) {
+ errlog(ERROR|FATAL, "Unable to determine file position\n");
+ }
+
+ while (fgets(buf, BUFSIZ, fp)) {
+ /* replace comments with single whitespace */
+ remcomment(buf);
+
+ /* get complete line */
+ buf2 = line_to_buf(buf2, buf); /* append buf to buf2 */
+ len = strlen(buf);
+ if (len > 1) {
+ while (buf[len-2] == '\\') {
+ if (!fgets(buf, BUFSIZ, fp)) {
+ buf2 = line_to_buf(buf2, buf);
+ break;
+ }
+ len = strlen(buf);
+ buf2 = line_to_buf(buf2, buf);
+ }
+ } /* end of 'get complete line' */
+
+ if (!non_empty(buf2)) { /* is line non empty */
+ free(buf2);
+ buf2 = NULL;
+ continue;
+ }
+ p = realloc(localvalue, sizeof (char)*(strlen(buf2)+1));
+ if (p == NULL) {
+ p = realloc(NULL,
+ sizeof (char)*(strlen(buf2)+1));
+ if (p == NULL) {
+ errlog(ERROR | FATAL,
+ "Error: unable to "
+ "allocate memory\n");
+ }
+ }
+ localvalue = p;
+ split(buf2, key, localvalue);
+ if (strcasecmp(key, "arch") == 0) {
+ char *alist = localvalue, *a;
+ has_arch = 1;
+ while ((a = strtok(alist, " ,\n")) != NULL) {
+ archset = arch_strtoi(a);
+ if (arch & archset) {
+ free(buf2);
+ free(p);
+ if (fseeko(fp, offset, SEEK_SET) < 0) {
+ errlog(ERROR|FATAL,
+ "%s", strerror(errno));
+ }
+ return (1);
+ }
+ alist = NULL;
+ }
+ } else if (strcasecmp(key, "end") == 0) {
+ break;
+ }
+ free(buf2);
+ buf2 = NULL;
+ }
+
+end:
+ free(buf2);
+ free(p);
+
+ if (fseeko(fp, offset, SEEK_SET) < 0) {
+ errlog(ERROR|FATAL, "%s", strerror(errno));
+ }
+ if (has_arch == 0)
+ return (1);
+
+ return (0);
+}
diff --git a/usr/src/cmd/abi/spectrans/parser/frontend.c b/usr/src/cmd/abi/spectrans/parser/frontend.c
new file mode 100644
index 0000000..db33b99
--- /dev/null
+++ b/usr/src/cmd/abi/spectrans/parser/frontend.c
@@ -0,0 +1,569 @@
+/*
+ * 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"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <dirent.h>
+#include <libgen.h>
+#include <sys/param.h>
+#include <errno.h>
+
+#include "parser.h"
+#include "errlog.h"
+
+static char const *ARCH_I386 = "i386";
+static char const *ARCH_SPARC = "sparc";
+static char const *ARCH_SPARCV9 = "sparcv9";
+static char const *ARCH_IA64 = "ia64";
+static char const *ARCH_AMD64 = "amd64";
+static char const *ARCH_ALL = "all";
+
+static int dofiles(const Translator_info *);
+static int read_spec(const Translator_info *, char *);
+
+static int Curlineno;
+
+xlator_keyword_t *keywordlist;
+
+/*
+ * frontend entry point
+ * returns the number of errors encountered
+ */
+int
+frontend(const Translator_info *T_info)
+{
+ int retval, i = 0, errors = 0;
+
+ keywordlist = xlator_init(T_info);
+ if (keywordlist == NULL) {
+ errlog(ERROR, "Error: Unable to get keywordlist\n");
+ return (1);
+ }
+
+ if (T_info->ti_verbosity >= STATUS) {
+ errlog(STATUS, "interesting keywords:\n");
+ while (keywordlist[i].key != NULL) {
+ errlog(STATUS, "\t%s\n", keywordlist[i].key);
+ ++i;
+ };
+ }
+
+ retval = xlator_startlib(T_info->ti_liblist);
+ switch (retval) {
+ case XLATOR_SKIP:
+ if (T_info->ti_verbosity >= STATUS)
+ errlog(STATUS, "Skipping %s\n", T_info->ti_liblist);
+ retval = 0;
+ break;
+
+ case XLATOR_NONFATAL:
+ ++errors;
+ retval = 0;
+ break;
+
+ case XLATOR_SUCCESS:
+ retval = dofiles(T_info);
+ errors += retval;
+ if ((retval = xlator_endlib()) != XLATOR_SUCCESS)
+ ++errors;
+ retval = 0;
+ break;
+
+ default:
+ errlog(ERROR | FATAL,
+ "Error: Invalid return code from xlator_startlib()\n");
+ exit(1);
+ }
+
+ if ((retval = xlator_end()) != XLATOR_SUCCESS)
+ ++errors;
+
+ return (errors);
+}
+
+/*
+ * dofiles(const Translator_info *T_info);
+ * iterate through files specified in the command line and process
+ * them one by one
+ * requires spec files to have a ".spec" suffix
+ * returns the number of errors;
+ */
+static int
+dofiles(const Translator_info *T_info)
+{
+ int nfiles, flen, findex, retval = 0, errors = 0;
+
+ nfiles = T_info->ti_nfiles;
+
+ for (findex = 0; findex < nfiles; ++findex) {
+ flen = strlen(filelist[findex]);
+ if ((flen <= 5) ||
+ strcmp(&filelist[findex][flen-5], ".spec") != 0) {
+ errlog(ERROR,
+ "Error: File specified does not have the "
+ ".spec extension: %s\n", filelist[findex]);
+ ++errors;
+ continue;
+ };
+ retval = read_spec(T_info, filelist[findex]);
+ errors += retval;
+ }
+ return (errors);
+}
+
+/*
+ * read_spec -
+ * Given a filename, this function will reads the spec file to
+ * recognize keywords which it passes along with the corresponding
+ * value to the back-end translator to process. The following
+ * back-end interfaces are called:
+ * xlator_startfile
+ * xlator_start_if
+ * xlator_take_kvpair
+ * xlator_end_if
+ * xlator_endfile
+ */
+static int
+read_spec(const Translator_info *T_info, char *spec_filename)
+{
+ FILE *spec_fp;
+ Meta_info meta_info;
+ char key[BUFSIZ], *value = NULL, *p = NULL;
+ char *buf2 = NULL;
+ int retval = 0, errors = 0, ki = 0; /* keyword indicator */
+ int start_if_fail = 0, skip_if = 0;
+ int extends_err = 0;
+
+ meta_info.mi_ext_cnt = 0; /* All info is non-extends */
+ meta_info.mi_flags = 0;
+
+ retval = xlator_startfile(spec_filename);
+
+ switch (retval) {
+ case XLATOR_SKIP:
+ if (T_info->ti_verbosity >= WARNING)
+ errlog(WARNING, "Warning: Skipping %s\n",
+ spec_filename);
+ return (errors);
+
+ case XLATOR_NONFATAL:
+ errlog(ERROR, "Error in xlator_startfile\n");
+ ++errors;
+ return (errors);
+
+ case XLATOR_SUCCESS:
+ break;
+
+ default:
+ errlog(ERROR,
+ "Error: Invalid return code from xlator_startfile()\n");
+ ++errors;
+ return (errors);
+ };
+
+ /* file processing */
+ spec_fp = fopen(spec_filename, "r");
+ if (spec_fp == NULL) {
+ errlog(ERROR, "Error: Unable to open spec file %s: %s\n",
+ spec_filename, strerror(errno));
+ ++errors;
+ return (errors);
+ }
+
+ (void) strncpy(meta_info.mi_filename, spec_filename, BUFSIZ);
+ meta_info.mi_line_number = 0;
+ Curlineno = meta_info.mi_line_number;
+ while (meta_info.mi_nlines = readline(&buf2, spec_fp)) {
+ meta_info.mi_line_number += meta_info.mi_nlines;
+ Curlineno = meta_info.mi_line_number;
+ if (!non_empty(buf2)) {
+ free(buf2);
+ buf2 = NULL;
+ continue;
+ }
+ p = realloc(value, sizeof (char)*(strlen(buf2)+1));
+ if (p == NULL) {
+ errlog(ERROR | FATAL,
+ "Error: Unable to allocate memory for "
+ "value: %d\n", errno);
+ }
+ value = p;
+ split(buf2, key, value);
+ ki = interesting_keyword(keywordlist, key);
+ switch (ki) {
+ case XLATOR_KW_FUNC: /* Function keyword */
+ case XLATOR_KW_DATA: /* Data keyword */
+ meta_info.mi_extended = 0;
+ retval = xlator_start_if(meta_info, ki, value);
+ switch (retval) {
+ case XLATOR_FATAL: /* FATAL ERROR */
+ if (T_info->ti_verbosity >= STATUS) {
+ errlog(STATUS,
+ "Error in xlator_start_if: ");
+ }
+ ++errors;
+ return (errors);
+ case XLATOR_NONFATAL: /* NON-FATAL ERROR */
+ if (T_info->ti_verbosity >= STATUS)
+ errlog(STATUS,
+ "Error in xlator_start_if\n");
+ ++errors;
+ start_if_fail = 1;
+ break;
+ case XLATOR_SUCCESS: /* OK */
+ start_if_fail = 0;
+ extends_err = check4extends(spec_filename,
+ value, T_info->ti_archtoken, spec_fp);
+ switch (extends_err) {
+ case -1: /* Error */
+ errlog(ERROR, "\"%s\", line %d: "
+ "Error occurred while "
+ "checking for extends clause\n",
+ spec_filename, Curlineno);
+ ++errors;
+ /*FALLTHRU*/
+ case 0: /* No Extends */
+ break;
+ case 1: /* Extends */
+ meta_info.mi_extended = 1;
+ extends_err = do_extends(meta_info,
+ T_info, value);
+ if (extends_err) {
+ errors += extends_err;
+ }
+ break;
+ default: /* Programmer Error */
+ errlog(ERROR | FATAL,
+ "Error: invalid return from "
+ "check4extends %d\n", extends_err);
+ }
+ break;
+ case XLATOR_SKIP: /* SKIP */
+ if (T_info->ti_verbosity >= WARNING)
+ errlog(WARNING, "Warning: Skipping "
+ "interface %s\n", value);
+ skip_if = 1;
+ start_if_fail = 0;
+ break;
+ default:
+ /* Invalid Return */
+ errlog(ERROR | FATAL,
+ "Error: Invalid return code "
+ "from xlator_start_if (): %d\n", retval);
+ }
+ break;
+ case XLATOR_KW_END: /* END keyword */
+ if (start_if_fail == 0 && skip_if == 0) {
+ retval = xlator_end_if(meta_info, value);
+ if (retval)
+ ++errors;
+ }
+ skip_if = 0;
+ break;
+ case XLATOR_KW_NOTFOUND:
+ if (T_info->ti_verbosity >= TRACING)
+ errlog(TRACING, "uninteresting keyword: %s\n",
+ key);
+ break;
+ default:
+ if (skip_if == 0 && start_if_fail == 0) {
+ retval = xlator_take_kvpair(meta_info,
+ ki, value);
+ if (retval) {
+ if (T_info->ti_verbosity >= STATUS)
+ errlog(STATUS, "Error in "
+ "xlator_take_kvpair\n");
+ ++errors;
+ }
+ }
+ }
+ free(buf2);
+ buf2 = NULL;
+ }
+
+ if ((retval = xlator_endfile()) != XLATOR_SUCCESS) {
+ if (T_info->ti_verbosity >= STATUS)
+ errlog(STATUS, "Error in xlator_endfile\n");
+ ++errors;
+ }
+ free(p);
+ (void) fclose(spec_fp);
+ return (errors);
+}
+
+/*
+ * interesting_keyword(char **keywordlist, const char *key) {
+ * returns the token associated with key if key is found in keywordlist
+ * returns XLATOR_KW_NOTFOUND if key is NOT found in keywordlist
+ * "Function" and "End" are always interesting, return XLATOR_KW_FUNC
+ * and XLATOR_KW_DATA respectively;
+ * "End" is always interesting, return XLATOR_KW_END;
+ *
+ */
+int
+interesting_keyword(xlator_keyword_t *keywordlist, const char *key)
+{
+ int i = 0;
+
+ if (strcasecmp(key, "data") == 0) {
+ return (XLATOR_KW_DATA);
+ }
+ if (strcasecmp(key, "function") == 0) {
+ return (XLATOR_KW_FUNC);
+ }
+
+ if (strcasecmp(key, "end") == 0)
+ return (XLATOR_KW_END);
+
+ while (keywordlist[i].key != NULL) {
+ if (strcasecmp(keywordlist[i].key, key) == 0)
+ return (keywordlist[i].token);
+ ++i;
+ }
+ return (XLATOR_KW_NOTFOUND);
+}
+
+/*
+ * line_to_buf(char *dest, const char *src) {
+ * appends src to dest, dynamically increasing the size of dest.
+ * replaces the trailing '\' continuation character with a space.
+ *
+ * if src is continuation of dest, dest != NULL, and
+ * the last character in dest before the newline must be a `\'
+ * if src is not continuation of dest, then dest must be NULL
+ */
+char *
+line_to_buf(char *dest, const char *src)
+{
+ int slen = strlen(src);
+ int dlen;
+
+ if (dest == NULL) {
+ /* We're being called for the first time */
+ dest = malloc(sizeof (char) * (slen + 1));
+ if (dest == NULL) {
+ errlog(ERROR | FATAL,
+ "Error: Unable to allocate memory for dest\n");
+ }
+ (void) strcpy(dest, src);
+ return (dest);
+ }
+
+ dlen = strlen(dest);
+
+ dest = realloc(dest, (size_t)(sizeof (char) * (dlen+slen+1)));
+ if (dest == NULL) {
+ errlog(ERROR | FATAL,
+ "Error: Unable to allocate memory for dest\n");
+ }
+
+ if (dlen > 1) {
+ /*
+ * remove continuation character
+ * we replace the '\' from the previous line with a space
+ */
+ if (dest[dlen-2] == '\\') {
+ dest[dlen-2] = ' ';
+ }
+ }
+
+ /* join the two strings */
+ (void) strcat(dest, src);
+
+ return (dest);
+}
+
+/*
+ * non_empty(const char *str)
+ * assumes str is non null
+ * checks if str is a non empty string
+ * returns 1 if string contains non whitespace
+ * returns 0 if string contains only whitespace
+ */
+int
+non_empty(const char *str)
+{
+ while (*str != '\0') {
+ if (!isspace(*str))
+ return (1);
+ ++str;
+ };
+ return (0);
+}
+
+/*
+ * split(const char *line, char *key, char *value);
+ * splits the line into keyword (key) and value pair
+ */
+void
+split(const char *line, char *key, char *value)
+{
+ char *p;
+
+ p = (char *)line;
+
+ /* skip leading whitespace */
+ while (isspace(*p)&& *p != '\0')
+ ++p;
+
+ /* copy keyword from line into key */
+ while (!isspace(*p) && *p != '\0')
+ *key++ = *p++;
+
+ *key = '\0';
+
+ /* skip whitespace */
+ while (isspace(*p) && *p != '\0')
+ p++;
+
+ (void) strcpy(value, p);
+
+}
+
+/*
+ * check4extends(char *filename, char *value, int arch, FILE *fp)
+ * if no arch keyword is found or there is a MATCHING arch keyword
+ * returns 1 if value is of the form "data|function name extends"
+ * -1 for error
+ * 0 no other keyword after the function name
+ * else
+ * return 0
+ *
+ * filename is used only for error reporting
+ */
+int
+check4extends(const char *filename, const char *value, int arch, FILE *fp)
+{
+ char fun[BUFSIZ];
+ char extends[BUFSIZ];
+ int n;
+
+ if (arch_match(fp, arch)) {
+ split(value, fun, extends);
+ n = strlen(extends);
+ if (extends[n-1] == '\n')
+ extends[n-1] = '\0';
+ if (strncasecmp("extends", extends, 7) == 0) {
+ return (1);
+ } else {
+ if (*extends != '\0') {
+ errlog(ERROR, "\"%s\", line %d: Error: "
+ "Trailing garbage after function name\n",
+ filename, Curlineno);
+ return (-1);
+ }
+ }
+ }
+ return (0);
+}
+
+/*
+ * remcomment (char *buf)
+ * replace comments with single whitespace
+ */
+/* XXX: There is currently no way to escape a comment character */
+void
+remcomment(char const *buf)
+{
+ char *p;
+ p = strchr(buf, '#');
+ if (p) {
+ *p = ' ';
+ *(p+1) = '\0';
+ }
+}
+
+/*
+ * arch_strtoi()
+ *
+ * input: string
+ * return: XLATOR_I386 if string == ARCH_I386
+ * XLATOR_SPARC if string == ARCH_SPARC
+ * XLATOR_SPARCV9 if string == ARCH_SPARCV9
+ * XLATOR_IA64 if string == ARCH_IA64
+ * XLATOR_AMD64 if string == ARCH_AMD64
+ * XLATOR_ALLARCH if string == ARCH_ALL
+ * 0 if outside the known set {i386, sparc, sparcv9, ia64, amd64}.
+ */
+int
+arch_strtoi(const char *arch_str)
+{
+ if (arch_str != NULL) {
+ if (strcmp(arch_str, ARCH_I386) == 0)
+ return (XLATOR_I386);
+ else if (strcmp(arch_str, ARCH_SPARC) == 0)
+ return (XLATOR_SPARC);
+ else if (strcmp(arch_str, ARCH_SPARCV9) == 0)
+ return (XLATOR_SPARCV9);
+ else if (strcmp(arch_str, ARCH_IA64) == 0)
+ return (XLATOR_IA64);
+ else if (strcmp(arch_str, ARCH_AMD64) == 0)
+ return (XLATOR_AMD64);
+ else if (strcmp(arch_str, ARCH_ALL) == 0)
+ return (XLATOR_ALLARCH);
+ } else {
+ errlog(ERROR, "\"%s\", line %d: Error: "
+ "arch keyword with no value");
+ }
+ return (0);
+}
+
+int
+readline(char **buffer, FILE *fp)
+{
+ int nlines = 0;
+ int len;
+ char buf[BUFSIZ];
+
+ if (fgets(buf, BUFSIZ, fp)) {
+ nlines++;
+ /* replace comments with single whitespace */
+ remcomment(buf);
+
+ /* get complete line */
+ *buffer = line_to_buf(*buffer, buf); /* append buf to buffer */
+ len = strlen(buf);
+ if (len > 1) {
+ /* handle continuation lines */
+ while (buf[len-2] == '\\') {
+ if (!fgets(buf, BUFSIZ, fp)) {
+ *buffer = line_to_buf(*buffer, buf);
+ break;
+ }
+ nlines++;
+ len = strlen(buf);
+ *buffer = line_to_buf(*buffer, buf);
+ }
+ } /* end of 'get complete line' */
+ }
+ return (nlines);
+}
diff --git a/usr/src/cmd/abi/spectrans/parser/i386/Makefile b/usr/src/cmd/abi/spectrans/parser/i386/Makefile
new file mode 100644
index 0000000..96eaa78
--- /dev/null
+++ b/usr/src/cmd/abi/spectrans/parser/i386/Makefile
@@ -0,0 +1,32 @@
+#
+# 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
+#
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1997-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# cmd/abi/daa2x/util/i386/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
diff --git a/usr/src/cmd/abi/spectrans/parser/main.c b/usr/src/cmd/abi/spectrans/parser/main.c
new file mode 100644
index 0000000..1e3046d
--- /dev/null
+++ b/usr/src/cmd/abi/spectrans/parser/main.c
@@ -0,0 +1,231 @@
+/*
+ * 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"
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <libgen.h>
+#include <ctype.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <errno.h>
+#include "parser.h"
+#include "errlog.h"
+
+#define SPEC_PARSER_VERSION "2.1"
+
+char **filelist;
+
+static char *prog;
+
+static void usage(void);
+
+int
+main(int argc, char **argv)
+{
+ int c, retval, size = 0;
+ int lflag = 0,
+ iflag = 0,
+ aflag = 0,
+ vflag = 0;
+ char *tmpptr;
+
+ Translator_info T_info;
+
+ prog = basename(argv[0]);
+
+ T_info.ti_verbosity = 0;
+ T_info.ti_flags = 0;
+ T_info.ti_dash_I = NULL;
+ T_info.ti_output_file = NULL;
+ T_info.ti_libtype = NORMALLIB;
+ T_info.ti_versfile = "version";
+
+ while ((c = getopt(argc, argv, "FVpd:v:l:o:I:a:")) != EOF) {
+ switch (c) {
+ case 'F':
+ /* Library is a filter */
+ T_info.ti_libtype = FILTERLIB;
+ break;
+ case 'a':
+ /* set the target architecture */
+ if ((T_info.ti_archtoken = arch_strtoi(optarg)) == 0) {
+ errlog(ERROR,
+ "Error: architecture specified must "
+ "be one of: i386, sparc, sparcv9, "
+ "ia64 or amd64\n");
+ usage();
+ }
+ T_info.ti_arch = optarg;
+ ++aflag;
+ break;
+ case 'V':
+ /* print the version info */
+ (void) fprintf(stderr,
+ "%s Version %s\n", prog, SPEC_PARSER_VERSION);
+ return (0);
+ break;
+ case 'd':
+ /* set debugging level */
+ if (!isdigit(*optarg) ||
+ (T_info.ti_verbosity = atoi(optarg)) < 0) {
+ errlog(ERROR,
+ "Error: -d option must be given a "
+ "positive integer argument\n");
+ usage();
+ }
+ break;
+ case 'l':
+ /* set library name */