xref: /illumos-gate/usr/src/tools/scripts/check_rtime.pl (revision 56acfad3590872afa6b09b3aec90c03ebe17ef21)
17c478bd9Sstevel@tonic-gate#!/usr/perl5/bin/perl -w
27c478bd9Sstevel@tonic-gate#
37c478bd9Sstevel@tonic-gate# CDDL HEADER START
47c478bd9Sstevel@tonic-gate#
57c478bd9Sstevel@tonic-gate# The contents of this file are subject to the terms of the
6749f21d3Swesolows# Common Development and Distribution License (the "License").
7749f21d3Swesolows# You may not use this file except in compliance with the License.
87c478bd9Sstevel@tonic-gate#
97c478bd9Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate# See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate# and limitations under the License.
137c478bd9Sstevel@tonic-gate#
147c478bd9Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate#
207c478bd9Sstevel@tonic-gate# CDDL HEADER END
217c478bd9Sstevel@tonic-gate#
22749f21d3Swesolows
237c478bd9Sstevel@tonic-gate#
245253169eSAli Bahrami# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
256112cec5SJoshua M. Clulow# Copyright 2020 Oxide Computer Company
267c478bd9Sstevel@tonic-gate#
27749f21d3Swesolows
28749f21d3Swesolows#
297c478bd9Sstevel@tonic-gate# Check ELF information.
307c478bd9Sstevel@tonic-gate#
310910f6b5SRichard Lowe# This script descends a directory hierarchy inspecting ELF objects.  The
320910f6b5SRichard Lowe# general theme is to verify that common Makefile rules have been used to
330910f6b5SRichard Lowe# build these objects.  Typical failures occur when Makefile rules are
340910f6b5SRichard Lowe# re-invented rather than being inherited from "cmd/lib" Makefiles.
357c478bd9Sstevel@tonic-gate#
367c478bd9Sstevel@tonic-gate# As always, a number of components don't follow the rules, and these are
3775ce41a5SAli Bahrami# excluded to reduce this scripts output.
387c478bd9Sstevel@tonic-gate#
397c478bd9Sstevel@tonic-gate# By default any file that has conditions that should be reported is first
407c478bd9Sstevel@tonic-gate# listed and then each condition follows.  The -o (one-line) option produces a
417c478bd9Sstevel@tonic-gate# more terse output which is better for sorting/diffing with "nightly".
427c478bd9Sstevel@tonic-gate#
437c478bd9Sstevel@tonic-gate# NOTE: missing dependencies, symbols or versions are reported by running the
447c478bd9Sstevel@tonic-gate# file through ldd(1).  As objects within a proto area are built to exist in a
457c478bd9Sstevel@tonic-gate# base system, standard use of ldd(1) will bind any objects to dependencies
467c478bd9Sstevel@tonic-gate# that exist in the base system.  It is frequently the case that newer objects
477c478bd9Sstevel@tonic-gate# exist in the proto area that are required to satisfy other objects
487c478bd9Sstevel@tonic-gate# dependencies, and without using these newer objects an ldd(1) will produce
4975ce41a5SAli Bahrami# misleading error messages.  To compensate for this, the -D/-d options, or the
5075ce41a5SAli Bahrami# existence of the CODEMSG_WS/ROOT environment variables, cause the creation of
517c478bd9Sstevel@tonic-gate# alternative dependency mappings via crle(1) configuration files that establish
527c478bd9Sstevel@tonic-gate# any proto shared objects as alternatives to their base system location.  Thus
537c478bd9Sstevel@tonic-gate# ldd(1) can be executed against these configuration files so that objects in a
547c478bd9Sstevel@tonic-gate# proto area bind to their dependencies in the same proto area.
557c478bd9Sstevel@tonic-gate
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate# Define all global variables (required for strict)
5813bb1409SRichard Loweuse vars  qw($Prog $Env $Ena64 $Tmpdir);
5975ce41a5SAli Bahramiuse vars  qw($LddNoU $Conf32 $Conf64);
6075ce41a5SAli Bahramiuse vars  qw(%opt);
6175ce41a5SAli Bahramiuse vars  qw($ErrFH $ErrTtl $InfoFH $InfoTtl $OutCnt1 $OutCnt2);
6275ce41a5SAli Bahrami
6375ce41a5SAli Bahrami# An exception file is used to specify regular expressions to match
6475ce41a5SAli Bahrami# objects. These directives specify special attributes of the object.
6575ce41a5SAli Bahrami# The regular expressions are read from the file and compiled into the
6675ce41a5SAli Bahrami# regular expression variables.
6775ce41a5SAli Bahrami#
6875ce41a5SAli Bahrami# The name of each regular expression variable is of the form
6975ce41a5SAli Bahrami#
7075ce41a5SAli Bahrami#	$EXRE_xxx
7175ce41a5SAli Bahrami#
7275ce41a5SAli Bahrami# where xxx is the name of the exception in lower case. For example,
7375ce41a5SAli Bahrami# the regular expression variable for EXEC_STACK is $EXRE_exec_stack.
7475ce41a5SAli Bahrami#
7575ce41a5SAli Bahrami# onbld_elfmod::LoadExceptionsToEXRE() depends on this naming convention
7675ce41a5SAli Bahrami# to initialize the regular expression variables, and to detect invalid
7775ce41a5SAli Bahrami# exception names.
7875ce41a5SAli Bahrami#
7975ce41a5SAli Bahrami# If a given exception is not used in the exception file, its regular
8075ce41a5SAli Bahrami# expression variable will be undefined. Users of these variables must
8175ce41a5SAli Bahrami# test the variable with defined() prior to use:
8275ce41a5SAli Bahrami#
8375ce41a5SAli Bahrami#	defined($EXRE_exec_stack) && ($foo =~ $EXRE_exec_stack)
8475ce41a5SAli Bahrami#
855253169eSAli Bahrami# or if the test is to make sure the item is not specified:
865253169eSAli Bahrami#
875253169eSAli Bahrami#	!defined($EXRE_exec_stack) || ($foo !~ $EXRE_exec_stack)
885253169eSAli Bahrami#
8975ce41a5SAli Bahrami# ----
9075ce41a5SAli Bahrami#
9175ce41a5SAli Bahrami# The exceptions are:
9275ce41a5SAli Bahrami#
935253169eSAli Bahrami#   EXEC_DATA
945253169eSAli Bahrami#	Objects that are not required to have non-executable writable
955253169eSAli Bahrami#	data segments.
965253169eSAli Bahrami#
9775ce41a5SAli Bahrami#   EXEC_STACK
9875ce41a5SAli Bahrami#	Objects that are not required to have a non-executable stack
9975ce41a5SAli Bahrami#
1009e593677SRichard Lowe#   FORBIDDEN_DEP
1019e593677SRichard Lowe#	Objects allowed to link to 'forbidden' objects
1029e593677SRichard Lowe#
1039e593677SRichard Lowe#   FORBIDDEN
1049e593677SRichard Lowe#	Objects to which nobody not excepted with FORBIDDEN_DEP may link
1059e593677SRichard Lowe#
1060910f6b5SRichard Lowe#   NOT_KMOD
1070910f6b5SRichard Lowe#	Objects that we think should be linked with -ztype=kmod but are
1080910f6b5SRichard Lowe#	allowed to not be.
1090910f6b5SRichard Lowe#
11075ce41a5SAli Bahrami#   NOCRLEALT
11175ce41a5SAli Bahrami#	Objects that should be skipped by AltObjectConfig() when building
11275ce41a5SAli Bahrami#	the crle script that maps objects to the proto area.
11375ce41a5SAli Bahrami#
11475ce41a5SAli Bahrami#    NODIRECT
11575ce41a5SAli Bahrami#	Objects that are not required to use direct bindings
11675ce41a5SAli Bahrami#
11775ce41a5SAli Bahrami#    NOSYMSORT
11875ce41a5SAli Bahrami#	Objects we should not check for duplicate addresses in
11975ce41a5SAli Bahrami#	the symbol sort sections.
12075ce41a5SAli Bahrami#
12175ce41a5SAli Bahrami#    OLDDEP
12275ce41a5SAli Bahrami#	Objects that are no longer needed because their functionalty
12375ce41a5SAli Bahrami#	has migrated elsewhere. These are usually pure filters that
12475ce41a5SAli Bahrami#	point at libc.
12575ce41a5SAli Bahrami#
12675ce41a5SAli Bahrami#    SKIP
12775ce41a5SAli Bahrami#	Files and directories that should be excluded from analysis.
12875ce41a5SAli Bahrami#
12975ce41a5SAli Bahrami#    STAB
13075ce41a5SAli Bahrami#	Objects that are allowed to contain stab debugging sections
13175ce41a5SAli Bahrami#
13275ce41a5SAli Bahrami#    TEXTREL
13375ce41a5SAli Bahrami#	Object for which relocations are allowed to the text segment
13475ce41a5SAli Bahrami#
13575ce41a5SAli Bahrami#    UNDEF_REF
13675ce41a5SAli Bahrami#	Objects that are allowed undefined references
13775ce41a5SAli Bahrami#
13875ce41a5SAli Bahrami#    UNREF_OBJ
13975ce41a5SAli Bahrami#	"unreferenced object=" ldd(1) diagnostics.
14075ce41a5SAli Bahrami#
14175ce41a5SAli Bahrami#    UNUSED_DEPS
14275ce41a5SAli Bahrami#	Objects that are allowed to have unused dependencies
14375ce41a5SAli Bahrami#
14475ce41a5SAli Bahrami#    UNUSED_OBJ
14575ce41a5SAli Bahrami#	Objects that are allowed to be unused dependencies
14675ce41a5SAli Bahrami#
14775ce41a5SAli Bahrami#    UNUSED_RPATH
14875ce41a5SAli Bahrami#	Objects with unused runpaths
14975ce41a5SAli Bahrami#
15075ce41a5SAli Bahrami
1515253169eSAli Bahramiuse vars  qw($EXRE_exec_data $EXRE_exec_stack $EXRE_nocrlealt);
1529e593677SRichard Loweuse vars  qw($EXRE_nodirect $EXRE_nosymsort $EXRE_forbidden_dep $EXRE_forbidden);
15375ce41a5SAli Bahramiuse vars  qw($EXRE_olddep $EXRE_skip $EXRE_stab $EXRE_textrel $EXRE_undef_ref);
15475ce41a5SAli Bahramiuse vars  qw($EXRE_unref_obj $EXRE_unused_deps $EXRE_unused_obj);
1550910f6b5SRichard Loweuse vars  qw($EXRE_unused_rpath $EXRE_no_comment $EXRE_not_kmod);
1567c478bd9Sstevel@tonic-gate
1577c478bd9Sstevel@tonic-gateuse strict;
1587c478bd9Sstevel@tonic-gateuse Getopt::Std;
15975ce41a5SAli Bahramiuse File::Basename;
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate# Reliably compare two OS revisions.  Arguments are <ver1> <op> <ver2>.
1637c478bd9Sstevel@tonic-gate# <op> is the string form of a normal numeric comparison operator.
1647c478bd9Sstevel@tonic-gatesub cmp_os_ver {
1657c478bd9Sstevel@tonic-gate	my @ver1 = split(/\./, $_[0]);
1667c478bd9Sstevel@tonic-gate	my $op = $_[1];
1677c478bd9Sstevel@tonic-gate	my @ver2 = split(/\./, $_[2]);
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate	push @ver2, ("0") x $#ver1 - $#ver2;
1707c478bd9Sstevel@tonic-gate	push @ver1, ("0") x $#ver2 - $#ver1;
1717c478bd9Sstevel@tonic-gate
1727c478bd9Sstevel@tonic-gate	my $diff = 0;
1737c478bd9Sstevel@tonic-gate	while (@ver1 || @ver2) {
1747c478bd9Sstevel@tonic-gate		if (($diff = shift(@ver1) - shift(@ver2)) != 0) {
1757c478bd9Sstevel@tonic-gate			last;
1767c478bd9Sstevel@tonic-gate		}
1777c478bd9Sstevel@tonic-gate	}
1787c478bd9Sstevel@tonic-gate	return (eval "$diff $op 0" ? 1 : 0);
1797c478bd9Sstevel@tonic-gate}
1807c478bd9Sstevel@tonic-gate
18175ce41a5SAli Bahrami## ProcFile(FullPath, RelPath, File, Class, Type, Verdef)
18275ce41a5SAli Bahrami#
1837c478bd9Sstevel@tonic-gate# Determine whether this a ELF dynamic object and if so investigate its runtime
1847c478bd9Sstevel@tonic-gate# attributes.
18575ce41a5SAli Bahrami#
1867c478bd9Sstevel@tonic-gatesub ProcFile {
18775ce41a5SAli Bahrami	my($FullPath, $RelPath, $Class, $Type, $Verdef) = @_;
18875ce41a5SAli Bahrami	my(@Elf, @Ldd, $Dyn, $Sym, $Stack);
18967e3a03eSrie	my($Sun, $Relsz, $Pltsz, $Tex, $Stab, $Strip, $Lddopt, $SymSort);
19075ce41a5SAli Bahrami	my($Val, $Header, $IsX86, $RWX, $UnDep);
1910910f6b5SRichard Lowe	my($HasDirectBinding, $HasKMOD);
1927c478bd9Sstevel@tonic-gate
19375ce41a5SAli Bahrami	# Ignore symbolic links
19475ce41a5SAli Bahrami	return if -l $FullPath;
19575ce41a5SAli Bahrami
19675ce41a5SAli Bahrami	# Is this an object or directory hierarchy we don't care about?
19775ce41a5SAli Bahrami	return if (defined($EXRE_skip) && ($RelPath =~ $EXRE_skip));
19875ce41a5SAli Bahrami
19975ce41a5SAli Bahrami	# Bail if we can't stat the file. Otherwise, note if it is SUID/SGID.
20075ce41a5SAli Bahrami	return if !stat($FullPath);
20175ce41a5SAli Bahrami	my $Secure = (-u _ || -g _) ? 1 : 0;
20275ce41a5SAli Bahrami
20375ce41a5SAli Bahrami	# Reset output message counts for new input file
20475ce41a5SAli Bahrami	$$ErrTtl = $$InfoTtl = 0;
20575ce41a5SAli Bahrami
2067c478bd9Sstevel@tonic-gate	@Ldd = 0;
2077c478bd9Sstevel@tonic-gate
2087c478bd9Sstevel@tonic-gate	# Determine whether we have access to inspect the file.
2097c478bd9Sstevel@tonic-gate	if (!(-r $FullPath)) {
21075ce41a5SAli Bahrami		onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
21175ce41a5SAli Bahrami		    "unable to inspect file: permission denied");
2127c478bd9Sstevel@tonic-gate		return;
2137c478bd9Sstevel@tonic-gate	}
2147c478bd9Sstevel@tonic-gate
2157c478bd9Sstevel@tonic-gate	# Determine whether we have a executable (static or dynamic) or a
2167c478bd9Sstevel@tonic-gate	# shared object.
21775ce41a5SAli Bahrami	@Elf = split(/\n/, `elfdump -epdcy $FullPath 2>&1`);
2187c478bd9Sstevel@tonic-gate
2190910f6b5SRichard Lowe	$Dyn = $Stack = $IsX86 = $RWX = $HasKMOD = 0;
2200910f6b5SRichard Lowe
2217c478bd9Sstevel@tonic-gate	$Header = 'None';
2227c478bd9Sstevel@tonic-gate	foreach my $Line (@Elf) {
2237c478bd9Sstevel@tonic-gate		# If we have an invalid file type (which we can tell from the
2247c478bd9Sstevel@tonic-gate		# first line), or we're processing an archive, bail.
2257c478bd9Sstevel@tonic-gate		if ($Header eq 'None') {
2267c478bd9Sstevel@tonic-gate			if (($Line =~ /invalid file/) ||
2275253169eSAli Bahrami			    ($Line =~ /\Q$FullPath\E(.*):/)) {
2287c478bd9Sstevel@tonic-gate				return;
2297c478bd9Sstevel@tonic-gate			}
2307c478bd9Sstevel@tonic-gate		}
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate		if ($Line =~ /^ELF Header/) {
2337c478bd9Sstevel@tonic-gate			$Header = 'Ehdr';
23475ce41a5SAli Bahrami			next;
23575ce41a5SAli Bahrami		}
2367c478bd9Sstevel@tonic-gate
23775ce41a5SAli Bahrami		if ($Line =~ /^Program Header/) {
2387c478bd9Sstevel@tonic-gate			$Header = 'Phdr';
2397c478bd9Sstevel@tonic-gate			$RWX = 0;
24075ce41a5SAli Bahrami			next;
24175ce41a5SAli Bahrami		}
2427c478bd9Sstevel@tonic-gate
24375ce41a5SAli Bahrami		if ($Line =~ /^Dynamic Section/) {
2447c478bd9Sstevel@tonic-gate			# A dynamic section indicates we're a dynamic object
2450910f6b5SRichard Lowe			$Header = 'Dyn';
2467c478bd9Sstevel@tonic-gate			$Dyn = 1;
24775ce41a5SAli Bahrami			next;
24875ce41a5SAli Bahrami		}
2497c478bd9Sstevel@tonic-gate
25075ce41a5SAli Bahrami		if (($Header eq 'Ehdr') && ($Line =~ /e_machine:/)) {
2517c478bd9Sstevel@tonic-gate			# If it's a X86 object, we need to enforce RW- data.
25275ce41a5SAli Bahrami			$IsX86 = 1 if $Line =~ /(EM_AMD64|EM_386)/;
25375ce41a5SAli Bahrami			next;
2547c478bd9Sstevel@tonic-gate		}
25575ce41a5SAli Bahrami
25675ce41a5SAli Bahrami		if (($Header eq 'Phdr') &&
2575253169eSAli Bahrami		    ($Line =~ /\[ PF_X\s+PF_W\s+PF_R \]/)) {
2587c478bd9Sstevel@tonic-gate			# RWX segment seen.
2597c478bd9Sstevel@tonic-gate			$RWX = 1;
26075ce41a5SAli Bahrami			next;
2617c478bd9Sstevel@tonic-gate		}
2627c478bd9Sstevel@tonic-gate
26375ce41a5SAli Bahrami		if (($Header eq 'Phdr') &&
26475ce41a5SAli Bahrami		    ($Line =~ /\[ PT_LOAD \]/ && $RWX && $IsX86)) {
26575ce41a5SAli Bahrami			# Seen an RWX PT_LOAD segment.
2665253169eSAli Bahrami			if (!defined($EXRE_exec_data) ||
2675253169eSAli Bahrami			    ($RelPath !~ $EXRE_exec_data)) {
26875ce41a5SAli Bahrami				onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
26975ce41a5SAli Bahrami				    "application requires non-executable " .
27075ce41a5SAli Bahrami				    "data\t<no -Mmapfile_noexdata?>");
27175ce41a5SAli Bahrami			}
27275ce41a5SAli Bahrami			next;
27375ce41a5SAli Bahrami		}
27475ce41a5SAli Bahrami
27575ce41a5SAli Bahrami		if (($Header eq 'Phdr') && ($Line =~ /\[ PT_SUNWSTACK \]/)) {
2767c478bd9Sstevel@tonic-gate			# This object defines a non-executable stack.
2777c478bd9Sstevel@tonic-gate			$Stack = 1;
27875ce41a5SAli Bahrami			next;
2797c478bd9Sstevel@tonic-gate		}
2800910f6b5SRichard Lowe
2810910f6b5SRichard Lowe		if (($Header eq 'Dyn') && ($Line =~ /SUNW_KMOD/)) {
2820910f6b5SRichard Lowe			$HasKMOD = 1;
2830910f6b5SRichard Lowe			next;
2840910f6b5SRichard Lowe		}
2857c478bd9Sstevel@tonic-gate	}
2867c478bd9Sstevel@tonic-gate
2870910f6b5SRichard Lowe	# Determine whether this ELF object has a conforming mcs(1) comment
2880910f6b5SRichard Lowe	# section.  If the correct $(POST_PROCESS) macros are used, only a 3
2890910f6b5SRichard Lowe	# or 4 line .comment section should exist containing one or two
2900910f6b5SRichard Lowe	# "@(#)illumos" identifying comments (one comment for a non-debug
2910910f6b5SRichard Lowe	# build, and two for a debug build). The results of the following
2920910f6b5SRichard Lowe	# split should be three or four lines, the last empty line being
2930910f6b5SRichard Lowe	# discarded by the split.
2946112cec5SJoshua M. Clulow	if ($opt{m} &&
2956112cec5SJoshua M. Clulow	    (!defined($EXRE_no_comment) || ($RelPath !~ $EXRE_no_comment))) {
2967c478bd9Sstevel@tonic-gate		my(@Mcs, $Con, $Dev);
2977c478bd9Sstevel@tonic-gate
2987c478bd9Sstevel@tonic-gate		@Mcs = split(/\n/, `mcs -p $FullPath 2>&1`);
2997c478bd9Sstevel@tonic-gate
3007c478bd9Sstevel@tonic-gate		$Con = $Dev = $Val = 0;
3017c478bd9Sstevel@tonic-gate		foreach my $Line (@Mcs) {
3027c478bd9Sstevel@tonic-gate			$Val++;
3037c478bd9Sstevel@tonic-gate
3046112cec5SJoshua M. Clulow			if (($Val == 3) && ($Line !~ /^@\(#\)illumos/)) {
3057c478bd9Sstevel@tonic-gate				$Con = 1;
3067c478bd9Sstevel@tonic-gate				last;
3077c478bd9Sstevel@tonic-gate			}
3086112cec5SJoshua M. Clulow			if (($Val == 4) && ($Line =~ /^@\(#\)illumos/)) {
3097c478bd9Sstevel@tonic-gate				$Dev = 1;
3107c478bd9Sstevel@tonic-gate				next;
3117c478bd9Sstevel@tonic-gate			}
3127c478bd9Sstevel@tonic-gate			if (($Dev == 0) && ($Val == 4)) {
3137c478bd9Sstevel@tonic-gate				$Con = 1;
3147c478bd9Sstevel@tonic-gate				last;
3157c478bd9Sstevel@tonic-gate			}
3167c478bd9Sstevel@tonic-gate			if (($Dev == 1) && ($Val == 5)) {
3177c478bd9Sstevel@tonic-gate				$Con = 1;
3187c478bd9Sstevel@tonic-gate				last;
3197c478bd9Sstevel@tonic-gate			}
3207c478bd9Sstevel@tonic-gate		}
3217c478bd9Sstevel@tonic-gate		if ($opt{m} && ($Con == 1)) {
32275ce41a5SAli Bahrami			onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
32375ce41a5SAli Bahrami		    "non-conforming mcs(1) comment\t<no \$(POST_PROCESS)?>");
3247c478bd9Sstevel@tonic-gate		}
3257c478bd9Sstevel@tonic-gate	}
3267c478bd9Sstevel@tonic-gate
3277c478bd9Sstevel@tonic-gate	# Applications should contain a non-executable stack definition.
32875ce41a5SAli Bahrami	if (($Type eq 'EXEC') && ($Stack == 0) &&
32975ce41a5SAli Bahrami	    (!defined($EXRE_exec_stack) || ($RelPath !~ $EXRE_exec_stack))) {
33075ce41a5SAli Bahrami		onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
33175ce41a5SAli Bahrami		    "non-executable stack required\t<no -Mmapfile_noexstk?>");
3327c478bd9Sstevel@tonic-gate	}
3337c478bd9Sstevel@tonic-gate
3340910f6b5SRichard Lowe	# Use ldd on dynamic objects unless it's a 64-bit object and we lack
3350910f6b5SRichard Lowe	# the hardware.
3360910f6b5SRichard Lowe	if (($Type ne 'REL') && (($Class == 32) || $Ena64)) {
337976d55c9Sab196087		my $LDDFullPath = $FullPath;
338976d55c9Sab196087
3397c478bd9Sstevel@tonic-gate		if ($Secure) {
3407c478bd9Sstevel@tonic-gate			# The execution of a secure application over an nfs file
3417c478bd9Sstevel@tonic-gate			# system mounted nosuid will result in warning messages
3427c478bd9Sstevel@tonic-gate			# being sent to /var/adm/messages.  As this type of
3437c478bd9Sstevel@tonic-gate			# environment can occur with root builds, move the file
3447c478bd9Sstevel@tonic-gate			# being investigated to a safe place first.  In addition
3457c478bd9Sstevel@tonic-gate			# remove its secure permission so that it can be
3467c478bd9Sstevel@tonic-gate			# influenced by any alternative dependency mappings.
3477c478bd9Sstevel@tonic-gate
34875ce41a5SAli Bahrami			my $File = $RelPath;
34975ce41a5SAli Bahrami			$File =~ s!^.*/!!;      # basename
35075ce41a5SAli Bahrami
3517c478bd9Sstevel@tonic-gate			my($TmpPath) = "$Tmpdir/$File";
3527c478bd9Sstevel@tonic-gate
353976d55c9Sab196087			system('cp', $LDDFullPath, $TmpPath);
3547c478bd9Sstevel@tonic-gate			chmod 0777, $TmpPath;
355976d55c9Sab196087			$LDDFullPath = $TmpPath;
3567c478bd9Sstevel@tonic-gate		}
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate		# Use ldd(1) to determine the objects relocatability and use.
3597c478bd9Sstevel@tonic-gate		# By default look for all unreferenced dependencies.  However,
3607c478bd9Sstevel@tonic-gate		# some objects have legitimate dependencies that they do not
3617c478bd9Sstevel@tonic-gate		# reference.
36275ce41a5SAli Bahrami		if ($LddNoU) {
3637c478bd9Sstevel@tonic-gate			$Lddopt = "-ru";
3647c478bd9Sstevel@tonic-gate		} else {
3657c478bd9Sstevel@tonic-gate			$Lddopt = "-rU";
3667c478bd9Sstevel@tonic-gate		}
367976d55c9Sab196087		@Ldd = split(/\n/, `ldd $Lddopt $Env $LDDFullPath 2>&1`);
3687c478bd9Sstevel@tonic-gate		if ($Secure) {
369976d55c9Sab196087			unlink $LDDFullPath;
3707c478bd9Sstevel@tonic-gate		}
3717c478bd9Sstevel@tonic-gate	}
3727c478bd9Sstevel@tonic-gate
3737c478bd9Sstevel@tonic-gate	$Val = 0;
3747c478bd9Sstevel@tonic-gate	$Sym = 5;
37567e3a03eSrie	$UnDep = 1;
3767c478bd9Sstevel@tonic-gate
37767e3a03eSrie	foreach my $Line (@Ldd) {
3787c478bd9Sstevel@tonic-gate
3797c478bd9Sstevel@tonic-gate		if ($Val == 0) {
3807c478bd9Sstevel@tonic-gate			$Val = 1;
3817c478bd9Sstevel@tonic-gate			# Make sure ldd(1) worked.  One possible failure is that
3827c478bd9Sstevel@tonic-gate			# this is an old ldd(1) prior to -e addition (4390308).
3837c478bd9Sstevel@tonic-gate			if ($Line =~ /usage:/) {
3847c478bd9Sstevel@tonic-gate				$Line =~ s/$/\t<old ldd(1)?>/;
38575ce41a5SAli Bahrami				onbld_elfmod::OutMsg($ErrFH, $ErrTtl,
38675ce41a5SAli Bahrami				    $RelPath, $Line);
3877c478bd9Sstevel@tonic-gate				last;
3887c478bd9Sstevel@tonic-gate			} elsif ($Line =~ /execution failed/) {
38975ce41a5SAli Bahrami				onbld_elfmod::OutMsg($ErrFH, $ErrTtl,
39075ce41a5SAli Bahrami				    $RelPath, $Line);
3917c478bd9Sstevel@tonic-gate				last;
3927c478bd9Sstevel@tonic-gate			}
3937c478bd9Sstevel@tonic-gate
3947c478bd9Sstevel@tonic-gate			# It's possible this binary can't be executed, ie. we've
3957c478bd9Sstevel@tonic-gate			# found a sparc binary while running on an intel system,
3967c478bd9Sstevel@tonic-gate			# or a sparcv9 binary on a sparcv7/8 system.
3977c478bd9Sstevel@tonic-gate			if ($Line =~ /wrong class/) {
39875ce41a5SAli Bahrami				onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
39975ce41a5SAli Bahrami				    "has wrong class or data encoding");
4007c478bd9Sstevel@tonic-gate				next;
4017c478bd9Sstevel@tonic-gate			}
4027c478bd9Sstevel@tonic-gate
4037c478bd9Sstevel@tonic-gate			# Historically, ldd(1) likes executable objects to have
40475ce41a5SAli Bahrami			# their execute bit set.
4050910f6b5SRichard Lowe			if (($Type eq 'EXEC' || $Type eq 'DYN' ||
4060910f6b5SRichard Lowe			     $HasKMOD == 1) && (!(-x $FullPath))) {
40775ce41a5SAli Bahrami				onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
40875ce41a5SAli Bahrami				    "is not executable");
4097c478bd9Sstevel@tonic-gate				next;
4107c478bd9Sstevel@tonic-gate			}
4117c478bd9Sstevel@tonic-gate		}
4127c478bd9Sstevel@tonic-gate
4137c478bd9Sstevel@tonic-gate		# Look for "file" or "versions" that aren't found.  Note that
4147c478bd9Sstevel@tonic-gate		# these lines will occur before we find any symbol referencing
4157c478bd9Sstevel@tonic-gate		# errors.
4160910f6b5SRichard Lowe		if (($Type ne 'REL') && ($Sym == 5) && ($Line =~ /not found\)/)) {
4177c478bd9Sstevel@tonic-gate			if ($Line =~ /file not found\)/) {
4187c478bd9Sstevel@tonic-gate				$Line =~ s/$/\t<no -zdefs?>/;
4197c478bd9Sstevel@tonic-gate			}
42075ce41a5SAli Bahrami			onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, $Line);
4217c478bd9Sstevel@tonic-gate			next;
4227c478bd9Sstevel@tonic-gate		}
4237c478bd9Sstevel@tonic-gate		# Look for relocations whose symbols can't be found.  Note, we
4247c478bd9Sstevel@tonic-gate		# only print out the first 5 relocations for any file as this
4257c478bd9Sstevel@tonic-gate		# output can be excessive.
4260910f6b5SRichard Lowe		if (($Type ne 'REL') && $Sym && ($Line =~ /symbol not found/)) {
4277c478bd9Sstevel@tonic-gate			# Determine if this file is allowed undefined
4287c478bd9Sstevel@tonic-gate			# references.
42975ce41a5SAli Bahrami			if (($Sym == 5) && defined($EXRE_undef_ref) &&
43075ce41a5SAli Bahrami			    ($RelPath =~ $EXRE_undef_ref)) {
4317c478bd9Sstevel@tonic-gate				$Sym = 0;
43267e3a03eSrie				next;
4337c478bd9Sstevel@tonic-gate			}
4347c478bd9Sstevel@tonic-gate			if ($Sym-- == 1) {
43575ce41a5SAli Bahrami				onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
43675ce41a5SAli Bahrami				    "continued ...") if !$opt{o};
4377c478bd9Sstevel@tonic-gate				next;
4387c478bd9Sstevel@tonic-gate			}
4397c478bd9Sstevel@tonic-gate			# Just print the symbol name.
4407c478bd9Sstevel@tonic-gate			$Line =~ s/$/\t<no -zdefs?>/;
44175ce41a5SAli Bahrami			onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, $Line);
4427c478bd9Sstevel@tonic-gate			next;
4437c478bd9Sstevel@tonic-gate		}
44467e3a03eSrie		# Look for any unused search paths.
44567e3a03eSrie		if ($Line =~ /unused search path=/) {
44675ce41a5SAli Bahrami			next if defined($EXRE_unused_rpath) &&
44775ce41a5SAli Bahrami			    ($Line =~ $EXRE_unused_rpath);
44875ce41a5SAli Bahrami
44967e3a03eSrie			if ($Secure) {
45067e3a03eSrie				$Line =~ s!$Tmpdir/!!;
45167e3a03eSrie			}
45267e3a03eSrie			$Line =~ s/^[ \t]*(.*)/\t$1\t<remove search path?>/;
45375ce41a5SAli Bahrami			onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, $Line);
45467e3a03eSrie			next;
45567e3a03eSrie		}
4569e593677SRichard Lowe
45767e3a03eSrie		# Look for unreferenced dependencies.  Note, if any unreferenced
45867e3a03eSrie		# objects are ignored, then set $UnDep so as to suppress any
45967e3a03eSrie		# associated unused-object messages.
46067e3a03eSrie		if ($Line =~ /unreferenced object=/) {
46175ce41a5SAli Bahrami			if (defined($EXRE_unref_obj) &&
46275ce41a5SAli Bahrami			    ($Line =~ $EXRE_unref_obj)) {
46367e3a03eSrie				$UnDep = 0;
46467e3a03eSrie				next;
46567e3a03eSrie			}
46667e3a03eSrie			if ($Secure) {
46767e3a03eSrie				$Line =~ s!$Tmpdir/!!;
46867e3a03eSrie			}
46975ce41a5SAli Bahrami			$Line =~ s/^[ \t]*(.*)/$1\t<remove lib or -zignore?>/;
47075ce41a5SAli Bahrami			onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, $Line);
47167e3a03eSrie			next;
47267e3a03eSrie		}
4737c478bd9Sstevel@tonic-gate		# Look for any unused dependencies.
474*56acfad3SMarcel Telka		if ($UnDep && ($Line =~ /unused .+=/)) {
47575ce41a5SAli Bahrami			# Skip if object is allowed to have unused dependencies
47675ce41a5SAli Bahrami			next if defined($EXRE_unused_deps) &&
47775ce41a5SAli Bahrami			    ($RelPath =~ $EXRE_unused_deps);
47875ce41a5SAli Bahrami
47975ce41a5SAli Bahrami			# Skip if dependency is always allowed to be unused
48075ce41a5SAli Bahrami			next if defined($EXRE_unused_obj) &&
48175ce41a5SAli Bahrami			    ($Line =~ $EXRE_unused_obj);
48275ce41a5SAli Bahrami
48375ce41a5SAli Bahrami			$Line =~ s!$Tmpdir/!! if $Secure;
48475ce41a5SAli Bahrami			$Line =~ s/^[ \t]*(.*)/$1\t<remove lib or -zignore?>/;
48575ce41a5SAli Bahrami			onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, $Line);
4867c478bd9Sstevel@tonic-gate			next;
4877c478bd9Sstevel@tonic-gate		}
4887c478bd9Sstevel@tonic-gate	}
4897c478bd9Sstevel@tonic-gate
4907c478bd9Sstevel@tonic-gate	# Reuse the elfdump(1) data to investigate additional dynamic linking
4917c478bd9Sstevel@tonic-gate	# information.
4927c478bd9Sstevel@tonic-gate
493dfb96a4fSab196087	$Sun = $Relsz = $Pltsz = $Dyn = $Stab = $SymSort = 0;
4947c478bd9Sstevel@tonic-gate	$Tex = $Strip = 1;
495f6acbf7cSrie	$HasDirectBinding = 0;
4960910f6b5SRichard Lowe	$HasKMOD = 0;
4977c478bd9Sstevel@tonic-gate
4987c478bd9Sstevel@tonic-gate	$Header = 'None';
4997c478bd9Sstevel@tonic-gateELF:	foreach my $Line (@Elf) {
5007c478bd9Sstevel@tonic-gate		# We're only interested in the section headers and the dynamic
5017c478bd9Sstevel@tonic-gate		# section.
5027c478bd9Sstevel@tonic-gate		if ($Line =~ /^Section Header/) {
5037c478bd9Sstevel@tonic-gate			$Header = 'Shdr';
5047c478bd9Sstevel@tonic-gate
5057c478bd9Sstevel@tonic-gate			if (($Sun == 0) && ($Line =~ /\.SUNW_reloc/)) {
5067c478bd9Sstevel@tonic-gate				# This object has a combined relocation section.
5077c478bd9Sstevel@tonic-gate				$Sun = 1;
5087c478bd9Sstevel@tonic-gate
5097c478bd9Sstevel@tonic-gate			} elsif (($Stab == 0) && ($Line =~ /\.stab/)) {
5107c478bd9Sstevel@tonic-gate				# This object contain .stabs sections
5117c478bd9Sstevel@tonic-gate				$Stab = 1;
512dfb96a4fSab196087			} elsif (($SymSort == 0) &&
513dfb96a4fSab196087				 ($Line =~ /\.SUNW_dyn(sym)|(tls)sort/)) {
514dfb96a4fSab196087				# This object contains a symbol sort section
515dfb96a4fSab196087				$SymSort = 1;
5167c478bd9Sstevel@tonic-gate			}
5177c478bd9Sstevel@tonic-gate
5187c478bd9Sstevel@tonic-gate			if (($Strip == 1) && ($Line =~ /\.symtab/)) {
5197c478bd9Sstevel@tonic-gate				# This object contains a complete symbol table.
5207c478bd9Sstevel@tonic-gate				$Strip = 0;
5217c478bd9Sstevel@tonic-gate			}
5227c478bd9Sstevel@tonic-gate			next;
5237c478bd9Sstevel@tonic-gate
5247c478bd9Sstevel@tonic-gate		} elsif ($Line =~ /^Dynamic Section/) {
5257c478bd9Sstevel@tonic-gate			$Header = 'Dyn';
5267c478bd9Sstevel@tonic-gate			next;
527f6acbf7cSrie		} elsif ($Line =~ /^Syminfo Section/) {
528f6acbf7cSrie			$Header = 'Syminfo';
529f6acbf7cSrie			next;
530f6acbf7cSrie		} elsif (($Header ne 'Dyn') && ($Header ne 'Syminfo')) {
531f6acbf7cSrie			next;
532f6acbf7cSrie		}
533f6acbf7cSrie
534f6acbf7cSrie		# Look into the Syminfo section.
535f6acbf7cSrie		# Does this object have at least one Directly Bound symbol?
536f6acbf7cSrie		if (($Header eq 'Syminfo')) {
537f6acbf7cSrie			my(@Symword);
538f6acbf7cSrie
539f6acbf7cSrie			if ($HasDirectBinding == 1) {
540f6acbf7cSrie				next;
541f6acbf7cSrie			}
542f6acbf7cSrie
543f6acbf7cSrie			@Symword = split(' ', $Line);
544f6acbf7cSrie
545f6acbf7cSrie			if (!defined($Symword[1])) {
546f6acbf7cSrie				next;
547f6acbf7cSrie			}
548f6acbf7cSrie			if ($Symword[1] =~ /B/) {
549f6acbf7cSrie				$HasDirectBinding = 1;
550f6acbf7cSrie			}
5517c478bd9Sstevel@tonic-gate			next;
5527c478bd9Sstevel@tonic-gate		}
5537c478bd9Sstevel@tonic-gate
5547c478bd9Sstevel@tonic-gate		# Does this object contain text relocations.
5550910f6b5SRichard Lowe		if ($Tex && ($Type ne 'REL') && ($Line =~ /TEXTREL/)) {
5567c478bd9Sstevel@tonic-gate			# Determine if this file is allowed text relocations.
55775ce41a5SAli Bahrami			if (defined($EXRE_textrel) &&
55875ce41a5SAli Bahrami			    ($RelPath =~ $EXRE_textrel)) {
5597c478bd9Sstevel@tonic-gate				$Tex = 0;
5607c478bd9Sstevel@tonic-gate				next ELF;
5617c478bd9Sstevel@tonic-gate			}
56275ce41a5SAli Bahrami			onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
563532883abSRichard Lowe			    "TEXTREL .dynamic tag\t\t\t<no -fpic?>");
5647c478bd9Sstevel@tonic-gate			$Tex = 0;
5657c478bd9Sstevel@tonic-gate			next;
5667c478bd9Sstevel@tonic-gate		}
5677c478bd9Sstevel@tonic-gate
5687c478bd9Sstevel@tonic-gate		# Does this file have any relocation sections (there are a few
5697c478bd9Sstevel@tonic-gate		# psr libraries with no relocations at all, thus a .SUNW_reloc
5707c478bd9Sstevel@tonic-gate		# section won't exist either).
5717c478bd9Sstevel@tonic-gate		if (($Relsz == 0) && ($Line =~ / RELA?SZ/)) {
5727c478bd9Sstevel@tonic-gate			$Relsz = hex((split(' ', $Line))[2]);
5737c478bd9Sstevel@tonic-gate			next;
5747c478bd9Sstevel@tonic-gate		}
5757c478bd9Sstevel@tonic-gate
5767c478bd9Sstevel@tonic-gate		# Does this file have any plt relocations.  If the plt size is
5777c478bd9Sstevel@tonic-gate		# equivalent to the total relocation size then we don't have
5787c478bd9Sstevel@tonic-gate		# any relocations suitable for combining into a .SUNW_reloc
5797c478bd9Sstevel@tonic-gate		# section.
5807c478bd9Sstevel@tonic-gate		if (($Pltsz == 0) && ($Line =~ / PLTRELSZ/)) {
5817c478bd9Sstevel@tonic-gate			$Pltsz = hex((split(' ', $Line))[2]);
5827c478bd9Sstevel@tonic-gate			next;
5837c478bd9Sstevel@tonic-gate		}
5847c478bd9Sstevel@tonic-gate
5857c478bd9Sstevel@tonic-gate		# Does this object have any dependencies.
58667e3a03eSrie		if ($Line =~ /NEEDED/) {
5877c478bd9Sstevel@tonic-gate			my($Need) = (split(' ', $Line))[3];
5887c478bd9Sstevel@tonic-gate
58975ce41a5SAli Bahrami			if (defined($EXRE_olddep) && ($Need =~ $EXRE_olddep)) {
59067e3a03eSrie				# Catch any old (unnecessary) dependencies.
59175ce41a5SAli Bahrami				onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
5929e593677SRichard Lowe				    "NEEDED=$Need\t<dependency no " .
5939e593677SRichard Lowe				    "longer necessary>");
5949e593677SRichard Lowe			} elsif ((defined($EXRE_forbidden) &&
5959e593677SRichard Lowe                                  ($Need =~ $EXRE_forbidden)) &&
5969e593677SRichard Lowe                                 (!defined($EXRE_forbidden_dep) ||
5979e593677SRichard Lowe                                  ($FullPath !~ $EXRE_forbidden_dep))) {
5989e593677SRichard Lowe				onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
5999e593677SRichard Lowe				    "NEEDED=$Need\t<forbidden dependency, " .
6009e593677SRichard Lowe				    "missing -nodefaultlibs?>");
60167e3a03eSrie			} elsif ($opt{i}) {
60267e3a03eSrie				# Under the -i (information) option print out
60367e3a03eSrie				# any useful dynamic entries.
60475ce41a5SAli Bahrami				onbld_elfmod::OutMsg($InfoFH, $InfoTtl, $RelPath,
60575ce41a5SAli Bahrami				    "NEEDED=$Need");
6067c478bd9Sstevel@tonic-gate			}
6077c478bd9Sstevel@tonic-gate			next;
6087c478bd9Sstevel@tonic-gate		}
6097c478bd9Sstevel@tonic-gate
610f6acbf7cSrie		# Is this object built with -B direct flag on?
611f6acbf7cSrie		if ($Line =~ / DIRECT /) {
612f6acbf7cSrie			$HasDirectBinding = 1;
613f6acbf7cSrie		}
614f6acbf7cSrie
6150910f6b5SRichard Lowe		if (($Header eq 'Dyn') && ($Line =~ /SUNW_KMOD/)) {
6160910f6b5SRichard Lowe			$HasKMOD = 1;
6170910f6b5SRichard Lowe		}
6180910f6b5SRichard Lowe
6197c478bd9Sstevel@tonic-gate		# Does this object specify a runpath.
6207c478bd9Sstevel@tonic-gate		if ($opt{i} && ($Line =~ /RPATH/)) {
6217c478bd9Sstevel@tonic-gate			my($Rpath) = (split(' ', $Line))[3];
62275ce41a5SAli Bahrami			onbld_elfmod::OutMsg($InfoFH, $InfoTtl,
62375ce41a5SAli Bahrami			    $RelPath, "RPATH=$Rpath");
6247c478bd9Sstevel@tonic-gate			next;
6257c478bd9Sstevel@tonic-gate		}
6267c478bd9Sstevel@tonic-gate	}
6277c478bd9Sstevel@tonic-gate
6287c478bd9Sstevel@tonic-gate	# A shared object, that contains non-plt relocations, should have a
6297c478bd9Sstevel@tonic-gate	# combined relocation section indicating it was built with -z combreloc.
63075ce41a5SAli Bahrami	if (($Type eq 'DYN') && $Relsz && ($Relsz != $Pltsz) && ($Sun == 0)) {
63175ce41a5SAli Bahrami		onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
6325253169eSAli Bahrami		    ".SUNW_reloc section missing\t\t<no -zcombreloc?>");
6337c478bd9Sstevel@tonic-gate	}
6347c478bd9Sstevel@tonic-gate
6350910f6b5SRichard Lowe	# A probable kernel module should be tagged
6360910f6b5SRichard Lowe	if (($Type eq 'REL') && ($RelPath =~ qr{(^|/)kernel/}) &&
6370910f6b5SRichard Lowe	    ($HasKMOD == 0)) {
6380910f6b5SRichard Lowe		if (!defined($EXRE_not_kmod) || ($RelPath !~ $EXRE_not_kmod)) {
6390910f6b5SRichard Lowe			onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
6400910f6b5SRichard Lowe			    "kernel object should be linked -ztype=kmod");
6410910f6b5SRichard Lowe		}
6420910f6b5SRichard Lowe	}
6430910f6b5SRichard Lowe
6447c478bd9Sstevel@tonic-gate	# No objects released to a customer should have any .stabs sections
6457c478bd9Sstevel@tonic-gate	# remaining, they should be stripped.
6467c478bd9Sstevel@tonic-gate	if ($opt{s} && $Stab) {
64775ce41a5SAli Bahrami		goto DONESTAB if defined($EXRE_stab) && ($RelPath =~ $EXRE_stab);
64875ce41a5SAli Bahrami
64975ce41a5SAli Bahrami		onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
65075ce41a5SAli Bahrami		    "debugging sections should be deleted\t<no strip -x?>");
6517c478bd9Sstevel@tonic-gate	}
6527c478bd9Sstevel@tonic-gate
653f6acbf7cSrie	# Identify an object that is not built with either -B direct or
654f6acbf7cSrie	# -z direct.
65575ce41a5SAli Bahrami	goto DONESTAB
65675ce41a5SAli Bahrami	    if (defined($EXRE_nodirect) && ($RelPath =~ $EXRE_nodirect));
65775ce41a5SAli Bahrami
658f6acbf7cSrie	if ($Relsz && ($HasDirectBinding == 0)) {
65975ce41a5SAli Bahrami		onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
66075ce41a5SAli Bahrami		 "object has no direct bindings\t<no -B direct or -z direct?>");
661f6acbf7cSrie	}
662f6acbf7cSrie
6637c478bd9Sstevel@tonic-gateDONESTAB:
6647c478bd9Sstevel@tonic-gate
6658ad60789Srie	# All objects should have a full symbol table to provide complete
6667c478bd9Sstevel@tonic-gate	# debugging stack traces.
66775ce41a5SAli Bahrami	onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
66875ce41a5SAli Bahrami	    "symbol table should not be stripped\t<remove -s?>") if $Strip;
669dfb96a4fSab196087
670dfb96a4fSab196087	# If there are symbol sort sections in this object, report on
671dfb96a4fSab196087	# any that have duplicate addresses.
67275ce41a5SAli Bahrami	ProcSymSort($FullPath, $RelPath) if $SymSort;
673bfed486aSAli Bahrami
674bfed486aSAli Bahrami	# If -v was specified, and the object has a version definition
675bfed486aSAli Bahrami	# section, generate output showing each public symbol and the
676bfed486aSAli Bahrami	# version it belongs to.
67775ce41a5SAli Bahrami	ProcVerdef($FullPath, $RelPath)
67875ce41a5SAli Bahrami	    if ($Verdef eq 'VERDEF') && $opt{v};
679dfb96a4fSab196087}
680dfb96a4fSab196087
681dfb96a4fSab196087
68275ce41a5SAli Bahrami## ProcSymSortOutMsg(RelPath, secname, addr, names...)
683dfb96a4fSab196087#
68475ce41a5SAli Bahrami# Call onbld_elfmod::OutMsg for a duplicate address error in a symbol sort
685dfb96a4fSab196087# section
686dfb96a4fSab196087#
687dfb96a4fSab196087sub ProcSymSortOutMsg {
68875ce41a5SAli Bahrami	my($RelPath, $secname, $addr, @names) = @_;
689dfb96a4fSab196087
69075ce41a5SAli Bahrami	onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
691dfb96a4fSab196087	    "$secname: duplicate $addr: ". join(', ', @names));
692dfb96a4fSab196087}
693dfb96a4fSab196087
694dfb96a4fSab196087
695dfb96a4fSab196087## ProcSymSort(FullPath, RelPath)
696dfb96a4fSab196087#
697dfb96a4fSab196087# Examine the symbol sort sections for the given object and report
698dfb96a4fSab196087# on any duplicate addresses found.  Ideally, mapfile directives
699dfb96a4fSab196087# should be used when building objects that have multiple symbols
700dfb96a4fSab196087# with the same address so that only one of them appears in the sort
701dfb96a4fSab196087# section. This saves space, reduces user confusion, and ensures that
702dfb96a4fSab196087# libproc and debuggers always display public names instead of symbols
703dfb96a4fSab196087# that are merely implementation details.
704dfb96a4fSab196087#
705dfb96a4fSab196087sub ProcSymSort {
706dfb96a4fSab196087
70775ce41a5SAli Bahrami	my($FullPath, $RelPath) = @_;
708dfb96a4fSab196087
709dfb96a4fSab196087	# If this object is exempt from checking, return quietly
71075ce41a5SAli Bahrami	return if defined($EXRE_nosymsort) && ($FullPath =~ $EXRE_nosymsort);
711dfb96a4fSab196087
712dfb96a4fSab196087
713dfb96a4fSab196087	open(SORT, "elfdump -S $FullPath|") ||
714dfb96a4fSab196087	    die "$Prog: Unable to execute elfdump (symbol sort sections)\n";
715dfb96a4fSab196087
716dfb96a4fSab196087	my $line;
717dfb96a4fSab196087	my $last_addr;
718dfb96a4fSab196087	my @dups = ();
719dfb96a4fSab196087	my $secname;
720dfb96a4fSab196087	while ($line = <SORT>) {
721dfb96a4fSab196087		chomp $line;
722dfb96a4fSab196087
723dfb96a4fSab196087		next if ($line eq '');
724dfb96a4fSab196087
725dfb96a4fSab196087		# If this is a header line, pick up the section name
726dfb96a4fSab196087		if ($line =~ /^Symbol Sort Section:\s+([^\s]+)\s+/) {
727dfb96a4fSab196087			$secname = $1;
728dfb96a4fSab196087
729dfb96a4fSab196087			# Every new section is followed by a column header line
730dfb96a4fSab196087			$line = <SORT>;		# Toss header line
731dfb96a4fSab196087
732dfb96a4fSab196087			# Flush anything left from previous section
73375ce41a5SAli Bahrami			ProcSymSortOutMsg($RelPath, $secname, $last_addr, @dups)
73475ce41a5SAli Bahrami			    if (scalar(@dups) > 1);
735dfb96a4fSab196087
736dfb96a4fSab196087			# Reset variables for new sort section
737dfb96a4fSab196087			$last_addr = '';
738dfb96a4fSab196087			@dups = ();
739dfb96a4fSab196087
740dfb96a4fSab196087			next;
741dfb96a4fSab196087		}
742dfb96a4fSab196087
743dfb96a4fSab196087		# Process symbol line
744dfb96a4fSab196087		my @fields = split /\s+/, $line;
745dfb96a4fSab196087		my $new_addr = $fields[2];
746169e20d9SAli Bahrami		my $new_type = $fields[8];
747dfb96a4fSab196087		my $new_name = $fields[9];
748607c61fdSab196087
749169e20d9SAli Bahrami		if ($new_type eq 'UNDEF') {
75075ce41a5SAli Bahrami			onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
751169e20d9SAli Bahrami			    "$secname: unexpected UNDEF symbol " .
752169e20d9SAli Bahrami			    "(link-editor error): $new_name");
753169e20d9SAli Bahrami			next;
754169e20d9SAli Bahrami		}
755169e20d9SAli Bahrami
756a854c1c1Sab196087		if ($new_addr eq $last_addr) {
757dfb96a4fSab196087			push @dups, $new_name;
758dfb96a4fSab196087		} else {
75975ce41a5SAli Bahrami			ProcSymSortOutMsg($RelPath, $secname,
760dfb96a4fSab196087			    $last_addr, @dups) if (scalar(@dups) > 1);
761dfb96a4fSab196087			@dups = ( $new_name );
762dfb96a4fSab196087			$last_addr = $new_addr;
763dfb96a4fSab196087		}
764dfb96a4fSab196087	}
765dfb96a4fSab196087
76675ce41a5SAli Bahrami	ProcSymSortOutMsg($RelPath, $secname, $last_addr, @dups)
767dfb96a4fSab196087		if (scalar(@dups) > 1);
768dfb96a4fSab196087
769dfb96a4fSab196087	close SORT;
7707c478bd9Sstevel@tonic-gate}
7717c478bd9Sstevel@tonic-gate
7727c478bd9Sstevel@tonic-gate
773bfed486aSAli Bahrami## ProcVerdef(FullPath, RelPath)
774bfed486aSAli Bahrami#
775bfed486aSAli Bahrami# Examine the version definition section for the given object and report
776bfed486aSAli Bahrami# each public symbol along with the version it belongs to.
777bfed486aSAli Bahrami#
778bfed486aSAli Bahramisub ProcVerdef {
779bfed486aSAli Bahrami
78075ce41a5SAli Bahrami	my($FullPath, $RelPath) = @_;
781bfed486aSAli Bahrami	my $line;
782bfed486aSAli Bahrami	my $cur_ver = '';
783bfed486aSAli Bahrami	my $tab = $opt{o} ? '' : "\t";
784bfed486aSAli Bahrami
785bfed486aSAli Bahrami	# pvs -dov provides information about the versioning hierarchy
786bfed486aSAli Bahrami	# in the file. Lines are of the format:
787bfed486aSAli Bahrami	#	path - version[XXX];
788bfed486aSAli Bahrami	# where [XXX] indicates optional information, such as flags
789bfed486aSAli Bahrami	# or inherited versions.
790bfed486aSAli Bahrami	#
791bfed486aSAli Bahrami	# Private versions are allowed to change freely, so ignore them.
792bfed486aSAli Bahrami	open(PVS, "pvs -dov $FullPath|") ||
793bfed486aSAli Bahrami	    die "$Prog: Unable to execute pvs (version definition section)\n";
794bfed486aSAli Bahrami
795bfed486aSAli Bahrami	while ($line = <PVS>) {
796bfed486aSAli Bahrami		chomp $line;
797bfed486aSAli Bahrami
798bfed486aSAli Bahrami		if ($line =~ /^[^\s]+\s+-\s+([^;]+)/) {
799bfed486aSAli Bahrami			my $ver = $1;
800bfed486aSAli Bahrami
801bfed486aSAli Bahrami			next if $ver =~ /private/i;
80275ce41a5SAli Bahrami			onbld_elfmod::OutMsg($InfoFH, $InfoTtl, $RelPath,
80375ce41a5SAli Bahrami			    "${tab}VERDEF=$ver");
804bfed486aSAli Bahrami		}
805bfed486aSAli Bahrami	}
806bfed486aSAli Bahrami	close PVS;
807bfed486aSAli Bahrami
808bfed486aSAli Bahrami	# pvs -dos lists the symbols assigned to each version definition.
809bfed486aSAli Bahrami	# Lines are of the format:
810bfed486aSAli Bahrami	#	path - version: symbol;
811bfed486aSAli Bahrami	#	path - version: symbol (size);
812bfed486aSAli Bahrami	# where the (size) is added to data items, but not for functions.
813bfed486aSAli Bahrami	# We strip off the size, if present.
814bfed486aSAli Bahrami
815bfed486aSAli Bahrami	open(PVS, "pvs -dos $FullPath|") ||
816bfed486aSAli Bahrami	    die "$Prog: Unable to execute pvs (version definition section)\n";
817bfed486aSAli Bahrami	while ($line = <PVS>) {
818bfed486aSAli Bahrami		chomp $line;
819bfed486aSAli Bahrami		if ($line =~ /^[^\s]+\s+-\s+([^:]+):\s*([^\s;]+)/) {
820bfed486aSAli Bahrami		    my $ver = $1;
821bfed486aSAli Bahrami		    my $sym = $2;
822bfed486aSAli Bahrami
823bfed486aSAli Bahrami		    next if $ver =~ /private/i;
824bfed486aSAli Bahrami
825bfed486aSAli Bahrami		    if ($opt{o}) {
82675ce41a5SAli Bahrami			onbld_elfmod::OutMsg($InfoFH, $InfoTtl, $RelPath,
827bfed486aSAli Bahrami			    "VERSION=$ver, SYMBOL=$sym");
828bfed486aSAli Bahrami		    } else {
829bfed486aSAli Bahrami			if ($cur_ver ne $ver) {
83075ce41a5SAli Bahrami			    onbld_elfmod::OutMsg($InfoFH, $InfoTtl,
83175ce41a5SAli Bahrami			        $RelPath, "VERSION=$ver");
832bfed486aSAli Bahrami			    $cur_ver = $ver;
833bfed486aSAli Bahrami			}
83475ce41a5SAli Bahrami			onbld_elfmod::OutMsg($InfoFH, $InfoTtl,
83575ce41a5SAli Bahrami			    $RelPath, "SYMBOL=$sym");
836bfed486aSAli Bahrami		    }
837bfed486aSAli Bahrami		}
838bfed486aSAli Bahrami	}
839bfed486aSAli Bahrami
840bfed486aSAli Bahrami	close PVS;
841bfed486aSAli Bahrami}
842bfed486aSAli Bahrami
843bfed486aSAli Bahrami
84475ce41a5SAli Bahrami## OpenFindElf(file, FileHandleRef, LineNumRef)
84575ce41a5SAli Bahrami#
84675ce41a5SAli Bahrami# Open file in 'find_elf -r' format, and return the value of
84775ce41a5SAli Bahrami# the opening PREFIX line.
84875ce41a5SAli Bahrami#
84975ce41a5SAli Bahrami# entry:
85075ce41a5SAli Bahrami#	file - file, or find_elf child process, to open
85175ce41a5SAli Bahrami#	FileHandleRef - Reference to file handle to open
85275ce41a5SAli Bahrami#	LineNumRef - Reference to integer to increment as lines are input
85375ce41a5SAli Bahrami#
85475ce41a5SAli Bahrami# exit:
85575ce41a5SAli Bahrami#	This routine issues a fatal error and does not return on error.
85675ce41a5SAli Bahrami#	Otherwise, the value of PREFIX is returned.
85775ce41a5SAli Bahrami#
85875ce41a5SAli Bahramisub OpenFindElf {
85975ce41a5SAli Bahrami	my ($file, $fh, $LineNum) = @_;
86075ce41a5SAli Bahrami	my $line;
86175ce41a5SAli Bahrami	my $prefix;
8627c478bd9Sstevel@tonic-gate
86375ce41a5SAli Bahrami	open($fh, $file) || die "$Prog: Unable to open: $file";
86475ce41a5SAli Bahrami	$$LineNum = 0;
86575ce41a5SAli Bahrami
86675ce41a5SAli Bahrami	# This script requires relative paths as created by 'find_elf -r'.
86775ce41a5SAli Bahrami	# When this is done, the first non-comment line will always
86875ce41a5SAli Bahrami	# be PREFIX. Obtain that line, or issue a fatal error.
86975ce41a5SAli Bahrami	while ($line = onbld_elfmod::GetLine($fh, $LineNum)) {
87075ce41a5SAli Bahrami		if ($line =~ /^PREFIX\s+(.*)$/i) {
87175ce41a5SAli Bahrami			$prefix = $1;
87275ce41a5SAli Bahrami			last;
8737c478bd9Sstevel@tonic-gate		}
8747c478bd9Sstevel@tonic-gate
87575ce41a5SAli Bahrami		die "$Prog: No PREFIX line seen on line $$LineNum: $file";
8767c478bd9Sstevel@tonic-gate	}
8777c478bd9Sstevel@tonic-gate
87875ce41a5SAli Bahrami	$prefix;
8797c478bd9Sstevel@tonic-gate}
8807c478bd9Sstevel@tonic-gate
8817c478bd9Sstevel@tonic-gate
88275ce41a5SAli Bahrami## ProcFindElf(file)
88375ce41a5SAli Bahrami#
88475ce41a5SAli Bahrami# Open the specified file, which must be produced by "find_elf -r",
88575ce41a5SAli Bahrami# and process the files it describes.
88675ce41a5SAli Bahrami#
88775ce41a5SAli Bahramisub ProcFindElf {
88875ce41a5SAli Bahrami	my $file = $_[0];
88975ce41a5SAli Bahrami	my $line;
89075ce41a5SAli Bahrami	my $LineNum;
89175ce41a5SAli Bahrami
89275ce41a5SAli Bahrami	my $prefix = OpenFindElf($file, \*FIND_ELF, \$LineNum);
89375ce41a5SAli Bahrami
89475ce41a5SAli Bahrami	while ($line = onbld_elfmod::GetLine(\*FIND_ELF, \$LineNum)) {
89575ce41a5SAli Bahrami		next if !($line =~ /^OBJECT\s/i);
89675ce41a5SAli Bahrami
89775ce41a5SAli Bahrami		my ($item, $class, $type, $verdef, $obj) =
89875ce41a5SAli Bahrami		    split(/\s+/, $line, 5);
89975ce41a5SAli Bahrami
90075ce41a5SAli Bahrami		ProcFile("$prefix/$obj", $obj, $class, $type, $verdef);
9017c478bd9Sstevel@tonic-gate	}
9027c478bd9Sstevel@tonic-gate
90375ce41a5SAli Bahrami	close FIND_ELF;
9047c478bd9Sstevel@tonic-gate}
9057c478bd9Sstevel@tonic-gate
90675ce41a5SAli Bahrami
90775ce41a5SAli Bahrami## AltObjectConfig(file)
90875ce41a5SAli Bahrami#
90975ce41a5SAli Bahrami# Recurse through a directory hierarchy looking for appropriate dependencies
91075ce41a5SAli Bahrami# to map from their standard system locations to the proto area via a crle
91175ce41a5SAli Bahrami# config file.
91275ce41a5SAli Bahrami#
91375ce41a5SAli Bahrami# entry:
91475ce41a5SAli Bahrami#	file - File of ELF objects, in 'find_elf -r' format, to examine.
91575ce41a5SAli Bahrami#
91675ce41a5SAli Bahrami# exit:
91775ce41a5SAli Bahrami#	Scripts are generated for the 32 and 64-bit cases to run crle
91875ce41a5SAli Bahrami#	and create runtime configuration files that will establish
91975ce41a5SAli Bahrami#	alternative dependency mappings for the objects identified.
92075ce41a5SAli Bahrami#
92175ce41a5SAli Bahrami#	$Env - Set to environment variable definitions that will cause
92275ce41a5SAli Bahrami#		the config files generated by this routine to be used
92375ce41a5SAli Bahrami#		by ldd.
92475ce41a5SAli Bahrami#	$Conf32, $Conf64 - Undefined, or set to the config files generated
92575ce41a5SAli Bahrami#		by this routine. If defined, the caller is responsible for
92675ce41a5SAli Bahrami#		unlinking the files before exiting.
92775ce41a5SAli Bahrami#
92875ce41a5SAli Bahramisub AltObjectConfig {
92975ce41a5SAli Bahrami	my $file = $_[0];
93075ce41a5SAli Bahrami	my ($Crle32, $Crle64);
93175ce41a5SAli Bahrami	my $line;
93275ce41a5SAli Bahrami	my $LineNum;
93375ce41a5SAli Bahrami	my $obj_path;
93475ce41a5SAli Bahrami	my $obj_active = 0;
93575ce41a5SAli Bahrami	my $obj_class;
93675ce41a5SAli Bahrami
93775ce41a5SAli Bahrami	my $prefix = OpenFindElf($file, \*FIND_ELF);
93875ce41a5SAli Bahrami
93975ce41a5SAli BahramiLINE:
94075ce41a5SAli Bahrami	while ($line = onbld_elfmod::GetLine(\*FIND_ELF, \$LineNum)) {
94175ce41a5SAli Bahrami	      ITEM: {
94275ce41a5SAli Bahrami
94375ce41a5SAli Bahrami			if ($line =~ /^OBJECT\s/i) {
94475ce41a5SAli Bahrami				my ($item, $class, $type, $verdef, $obj) =
94575ce41a5SAli Bahrami				    split(/\s+/, $line, 5);
94675ce41a5SAli Bahrami
94775ce41a5SAli Bahrami				if ($type eq 'DYN') {
94875ce41a5SAli Bahrami					$obj_active = 1;
94975ce41a5SAli Bahrami					$obj_path = $obj;
95075ce41a5SAli Bahrami					$obj_class = $class;
95175ce41a5SAli Bahrami				} else {
95275ce41a5SAli Bahrami					# Only want sharable objects
95375ce41a5SAli Bahrami					$obj_active = 0;
9547c478bd9Sstevel@tonic-gate				}
95575ce41a5SAli Bahrami				last ITEM;
9567c478bd9Sstevel@tonic-gate			}
9577c478bd9Sstevel@tonic-gate
95875ce41a5SAli Bahrami			# We need to follow links to sharable objects so
95975ce41a5SAli Bahrami			# that any dependencies are expressed in all their
96075ce41a5SAli Bahrami			# available forms. We depend on ALIAS lines directly
96175ce41a5SAli Bahrami			# following the object they alias, so if we have
96275ce41a5SAli Bahrami			# a current object, this alias belongs to it.
96375ce41a5SAli Bahrami			if ($obj_active && ($line =~ /^ALIAS\s/i)) {
96475ce41a5SAli Bahrami				my ($item, $real_obj, $obj) =
96575ce41a5SAli Bahrami				    split(/\s+/, $line, 3);
96675ce41a5SAli Bahrami				$obj_path = $obj;
96775ce41a5SAli Bahrami				last ITEM;
9687c478bd9Sstevel@tonic-gate			}
9697c478bd9Sstevel@tonic-gate
97075ce41a5SAli Bahrami			# Skip unrecognized item
97175ce41a5SAli Bahrami			next LINE;
97275ce41a5SAli Bahrami		}
9737c478bd9Sstevel@tonic-gate
97475ce41a5SAli Bahrami		next if !$obj_active;
9757c478bd9Sstevel@tonic-gate
97675ce41a5SAli Bahrami		my $full = "$prefix/$obj_path";
97775ce41a5SAli Bahrami
97875ce41a5SAli Bahrami		next if defined($EXRE_nocrlealt) &&
97975ce41a5SAli Bahrami		    ($obj_path =~ $EXRE_nocrlealt);
98075ce41a5SAli Bahrami
98175ce41a5SAli Bahrami		my $Dir = $full;
98275ce41a5SAli Bahrami		$Dir =~ s/^(.*)\/.*$/$1/;
98375ce41a5SAli Bahrami
98475ce41a5SAli Bahrami		# Create a crle(1) script for the dependency we've found.
98575ce41a5SAli Bahrami		# We build separate scripts for the 32 and 64-bit cases.
98675ce41a5SAli Bahrami		# We create and initialize each script when we encounter
98775ce41a5SAli Bahrami		# the first object that needs it.
98875ce41a5SAli Bahrami		if ($obj_class == 32) {
9897c478bd9Sstevel@tonic-gate			if (!$Crle32) {
9907c478bd9Sstevel@tonic-gate				$Crle32 = "$Tmpdir/$Prog.crle32.$$";
9917c478bd9Sstevel@tonic-gate				open(CRLE32, "> $Crle32") ||
9927c478bd9Sstevel@tonic-gate				    die "$Prog: open failed: $Crle32: $!";
9937c478bd9Sstevel@tonic-gate				print CRLE32 "#!/bin/sh\ncrle \\\n";
9947c478bd9Sstevel@tonic-gate			}
99575ce41a5SAli Bahrami			print CRLE32 "\t-o $Dir -a /$obj_path \\\n";
99675ce41a5SAli Bahrami		} elsif ($Ena64) {
99775ce41a5SAli Bahrami			if (!$Crle64) {
99875ce41a5SAli Bahrami				$Crle64 = "$Tmpdir/$Prog.crle64.$$";
99975ce41a5SAli Bahrami				open(CRLE64, "> $Crle64") ||
100075ce41a5SAli Bahrami				    die "$Prog: open failed: $Crle64: $!";
100175ce41a5SAli Bahrami				print CRLE64 "#!/bin/sh\ncrle -64\\\n";
100275ce41a5SAli Bahrami			}
100375ce41a5SAli Bahrami			print CRLE64 "\t-o $Dir -a /$obj_path \\\n";
100475ce41a5SAli Bahrami		}
10057c478bd9Sstevel@tonic-gate	}
10067c478bd9Sstevel@tonic-gate
100775ce41a5SAli Bahrami	close FIND_ELF;
10087c478bd9Sstevel@tonic-gate
100975ce41a5SAli Bahrami
101075ce41a5SAli Bahrami	# Now that the config scripts are complete, use them to generate
101175ce41a5SAli Bahrami	# runtime linker config files.
10127c478bd9Sstevel@tonic-gate	if ($Crle64) {
10137c478bd9Sstevel@tonic-gate		$Conf64 = "$Tmpdir/$Prog.conf64.$$";
10147c478bd9Sstevel@tonic-gate		print CRLE64 "\t-c $Conf64\n";
10157c478bd9Sstevel@tonic-gate
10167c478bd9Sstevel@tonic-gate		chmod 0755, $Crle64;
10177c478bd9Sstevel@tonic-gate		close CRLE64;
10187c478bd9Sstevel@tonic-gate
101975ce41a5SAli Bahrami		undef $Conf64 if system($Crle64);
102075ce41a5SAli Bahrami
102175ce41a5SAli Bahrami		# Done with the script
102275ce41a5SAli Bahrami		unlink $Crle64;
10237c478bd9Sstevel@tonic-gate	}
10247c478bd9Sstevel@tonic-gate	if ($Crle32) {
10257c478bd9Sstevel@tonic-gate		$Conf32 = "$Tmpdir/$Prog.conf32.$$";
10267c478bd9Sstevel@tonic-gate		print CRLE32 "\t-c $Conf32\n";
10277c478bd9Sstevel@tonic-gate
10287c478bd9Sstevel@tonic-gate		chmod 0755, $Crle32;
10297c478bd9Sstevel@tonic-gate		close CRLE32;
10307c478bd9Sstevel@tonic-gate
103175ce41a5SAli Bahrami		undef $Conf32 if system($Crle32);
103275ce41a5SAli Bahrami
103375ce41a5SAli Bahrami		# Done with the script
103475ce41a5SAli Bahrami		unlink $Crle32;
10357c478bd9Sstevel@tonic-gate	}
10367c478bd9Sstevel@tonic-gate
103775ce41a5SAli Bahrami	# Set $Env so that we will use the config files generated above
103875ce41a5SAli Bahrami	# when we run ldd.
10397c478bd9Sstevel@tonic-gate	if ($Crle64 && $Conf64 && $Crle32 && $Conf32) {
10407c478bd9Sstevel@tonic-gate		$Env = "-e LD_FLAGS=config_64=$Conf64,config_32=$Conf32";
10417c478bd9Sstevel@tonic-gate	} elsif ($Crle64 && $Conf64) {
10427c478bd9Sstevel@tonic-gate		$Env = "-e LD_FLAGS=config_64=$Conf64";
10437c478bd9Sstevel@tonic-gate	} elsif ($Crle32 && $Conf32) {
10447c478bd9Sstevel@tonic-gate		$Env = "-e LD_FLAGS=config_32=$Conf32";
10457c478bd9Sstevel@tonic-gate	}
10467c478bd9Sstevel@tonic-gate}
10477c478bd9Sstevel@tonic-gate
104875ce41a5SAli Bahrami# -----------------------------------------------------------------------------
10497c478bd9Sstevel@tonic-gate
105075ce41a5SAli Bahrami# This script relies on ldd returning output reflecting only the binary
105175ce41a5SAli Bahrami# contents.  But if LD_PRELOAD* environment variables are present, libraries
105275ce41a5SAli Bahrami# named by them will also appear in the output, disrupting our analysis.
105375ce41a5SAli Bahrami# So, before we get too far, scrub the environment.
10547c478bd9Sstevel@tonic-gate
105575ce41a5SAli Bahramidelete($ENV{LD_PRELOAD});
105675ce41a5SAli Bahramidelete($ENV{LD_PRELOAD_32});
105775ce41a5SAli Bahramidelete($ENV{LD_PRELOAD_64});
10587c478bd9Sstevel@tonic-gate
105975ce41a5SAli Bahrami# Establish a program name for any error diagnostics.
106075ce41a5SAli Bahramichomp($Prog = `basename $0`);
10617c478bd9Sstevel@tonic-gate
106275ce41a5SAli Bahrami# The onbld_elfmod package is maintained in the same directory as this
106375ce41a5SAli Bahrami# script, and is installed in ../lib/perl. Use the local one if present,
106475ce41a5SAli Bahrami# and the installed one otherwise.
106575ce41a5SAli Bahramimy $moddir = dirname($0);
106675ce41a5SAli Bahrami$moddir = "$moddir/../lib/perl" if ! -f "$moddir/onbld_elfmod.pm";
106775ce41a5SAli Bahramirequire "$moddir/onbld_elfmod.pm";
106875ce41a5SAli Bahrami
106975ce41a5SAli Bahrami# Determine what machinery is available.
107075ce41a5SAli Bahramimy $Mach = `uname -p`;
107175ce41a5SAli Bahramimy$Isalist = `isalist`;
107275ce41a5SAli Bahramiif ($Mach =~ /sparc/) {
107375ce41a5SAli Bahrami	if ($Isalist =~ /sparcv9/) {
107475ce41a5SAli Bahrami		$Ena64 = "ok";
107575ce41a5SAli Bahrami	}
107675ce41a5SAli Bahrami} elsif ($Mach =~ /i386/) {
107775ce41a5SAli Bahrami	if ($Isalist =~ /amd64/) {
107875ce41a5SAli Bahrami		$Ena64 = "ok";
10794840e086Srie	}
10804840e086Srie}
10814840e086Srie
108275ce41a5SAli Bahrami# $Env is used with all calls to ldd. It is set by AltObjectConfig to
108375ce41a5SAli Bahrami# cause an alternate object mapping runtime config file to be used.
108475ce41a5SAli Bahrami$Env = '';
10857c478bd9Sstevel@tonic-gate
108675ce41a5SAli Bahrami# Check that we have arguments.
108775ce41a5SAli Bahramiif ((getopts('D:d:E:e:f:I:imosvw:', \%opt) == 0) ||
108875ce41a5SAli Bahrami    (!$opt{f} && ($#ARGV == -1))) {
108975ce41a5SAli Bahrami	print "usage: $Prog [-imosv] [-D depfile | -d depdir] [-E errfile]\n";
109075ce41a5SAli Bahrami	print "\t\t[-e exfile] [-f listfile] [-I infofile] [-w outdir]\n";
109175ce41a5SAli Bahrami	print "\t\t[file | dir]...\n";
109275ce41a5SAli Bahrami	print "\n";
109375ce41a5SAli Bahrami	print "\t[-D depfile]\testablish dependencies from 'find_elf -r' file list\n";
109475ce41a5SAli Bahrami	print "\t[-d depdir]\testablish dependencies from under directory\n";
109575ce41a5SAli Bahrami	print "\t[-E errfile]\tdirect error output to file\n";
109675ce41a5SAli Bahrami	print "\t[-e exfile]\texceptions file\n";
109775ce41a5SAli Bahrami	print "\t[-f listfile]\tuse file list produced by find_elf -r\n";
109875ce41a5SAli Bahrami	print "\t[-I infofile]\tdirect informational output (-i, -v) to file\n";
109975ce41a5SAli Bahrami	print "\t[-i]\t\tproduce dynamic table entry information\n";
110075ce41a5SAli Bahrami	print "\t[-m]\t\tprocess mcs(1) comments\n";
110175ce41a5SAli Bahrami	print "\t[-o]\t\tproduce one-liner output (prefixed with pathname)\n";
110275ce41a5SAli Bahrami	print "\t[-s]\t\tprocess .stab and .symtab entries\n";
110375ce41a5SAli Bahrami	print "\t[-v]\t\tprocess version definition entries\n";
110475ce41a5SAli Bahrami	print "\t[-w outdir]\tinterpret all files relative to given directory\n";
110575ce41a5SAli Bahrami	exit 1;
110675ce41a5SAli Bahrami}
110775ce41a5SAli Bahrami
110875ce41a5SAli Bahramidie "$Prog: -D and -d options are mutually exclusive\n" if ($opt{D} && $opt{d});
110975ce41a5SAli Bahrami
111075ce41a5SAli Bahrami$Tmpdir = "/tmp" if (!($Tmpdir = $ENV{TMPDIR}) || (! -d $Tmpdir));
111175ce41a5SAli Bahrami
111275ce41a5SAli Bahrami# If -w, change working directory to given location
111375ce41a5SAli Bahrami!$opt{w} || chdir($opt{w}) || die "$Prog: can't cd to $opt{w}";
111475ce41a5SAli Bahrami
111575ce41a5SAli Bahrami# Locate and process the exceptions file
111675ce41a5SAli Bahramionbld_elfmod::LoadExceptionsToEXRE('check_rtime');
111775ce41a5SAli Bahrami
111875ce41a5SAli Bahrami# Is there a proto area available, either via the -d option, or because
111975ce41a5SAli Bahrami# we are part of an activated workspace?
112075ce41a5SAli Bahramimy $Proto;
112175ce41a5SAli Bahramiif ($opt{d}) {
112275ce41a5SAli Bahrami	# User specified dependency directory - make sure it exists.
112375ce41a5SAli Bahrami	-d $opt{d} || die "$Prog: $opt{d} is not a directory\n";
112475ce41a5SAli Bahrami	$Proto = $opt{d};
112575ce41a5SAli Bahrami} elsif ($ENV{CODEMGR_WS}) {
112675ce41a5SAli Bahrami	my $Root;
112775ce41a5SAli Bahrami
112875ce41a5SAli Bahrami	# Without a user specified dependency directory see if we're
112975ce41a5SAli Bahrami	# part of a codemanager workspace and if a proto area exists.
113075ce41a5SAli Bahrami	$Proto = $Root if ($Root = $ENV{ROOT}) && (-d $Root);
113175ce41a5SAli Bahrami}
113275ce41a5SAli Bahrami
113375ce41a5SAli Bahrami# If we are basing this analysis off the sharable objects found in
113475ce41a5SAli Bahrami# a proto area, then gather dependencies and construct an alternative
113575ce41a5SAli Bahrami# dependency mapping via a crle(1) configuration file.
113675ce41a5SAli Bahrami#
113775ce41a5SAli Bahrami# To support alternative dependency mapping we'll need ldd(1)'s
113875ce41a5SAli Bahrami# -e option.  This is relatively new (s81_30), so make sure
113975ce41a5SAli Bahrami# ldd(1) is capable before gathering any dependency information.
114075ce41a5SAli Bahramiif ($opt{D} || $Proto) {
114175ce41a5SAli Bahrami	if (system('ldd -e /usr/lib/lddstub 2> /dev/null')) {
114275ce41a5SAli Bahrami		print "ldd: does not support -e, unable to ";
114375ce41a5SAli Bahrami		print "create alternative dependency mappingings.\n";
114475ce41a5SAli Bahrami		print "ldd: option added under 4390308 (s81_30).\n\n";
11457c478bd9Sstevel@tonic-gate	} else {
114675ce41a5SAli Bahrami		# If -D was specified, it supplies a list of files in
114775ce41a5SAli Bahrami		# 'find_elf -r' format, and can use it directly. Otherwise,
114875ce41a5SAli Bahrami		# we will run find_elf as a child process to find the
114975ce41a5SAli Bahrami		# sharable objects found under $Proto.
115075ce41a5SAli Bahrami		AltObjectConfig($opt{D} ? $opt{D} : "find_elf -frs $Proto|");
11517c478bd9Sstevel@tonic-gate	}
11527c478bd9Sstevel@tonic-gate}
11537c478bd9Sstevel@tonic-gate
115475ce41a5SAli Bahrami# To support unreferenced dependency detection we'll need ldd(1)'s -U
115575ce41a5SAli Bahrami# option.  This is relatively new (4638070), and if not available we
115675ce41a5SAli Bahrami# can still fall back to -u.  Even with this option, don't use -U with
115775ce41a5SAli Bahrami# releases prior to 5.10 as the cleanup for -U use only got integrated
115875ce41a5SAli Bahrami# into 5.10 under 4642023.  Note, that nightly doesn't typically set a
115975ce41a5SAli Bahrami# RELEASE from the standard <env> files.  Users who wish to disable use
116075ce41a5SAli Bahrami# of ldd(1)'s -U should set (or uncomment) RELEASE in their <env> file
116175ce41a5SAli Bahrami# if using nightly, or otherwise establish it in their environment.
116275ce41a5SAli Bahramiif (system('ldd -U /usr/lib/lddstub 2> /dev/null')) {
116375ce41a5SAli Bahrami	$LddNoU = 1;
116475ce41a5SAli Bahrami} else {
116575ce41a5SAli Bahrami	my($Release);
116675ce41a5SAli Bahrami
116775ce41a5SAli Bahrami	if (($Release = $ENV{RELEASE}) && (cmp_os_ver($Release, "<", "5.10"))) {
116875ce41a5SAli Bahrami		$LddNoU = 1;
116975ce41a5SAli Bahrami	} else {
117075ce41a5SAli Bahrami		$LddNoU = 0;
117175ce41a5SAli Bahrami	}
11727c478bd9Sstevel@tonic-gate}
11737c478bd9Sstevel@tonic-gate
117475ce41a5SAli Bahrami# Set up variables used to handle output files:
117575ce41a5SAli Bahrami#
117675ce41a5SAli Bahrami# Error messages go to stdout unless -E is specified. $ErrFH is a
117775ce41a5SAli Bahrami# file handle reference that points at the file handle where error messages
117875ce41a5SAli Bahrami# are sent, and $ErrTtl is a reference that points at an integer used
117975ce41a5SAli Bahrami# to count how many lines have been sent there.
118075ce41a5SAli Bahrami#
118175ce41a5SAli Bahrami# Informational messages go to stdout unless -I is specified. $InfoFH is a
118275ce41a5SAli Bahrami# file handle reference that points at the file handle where info messages
118375ce41a5SAli Bahrami# are sent, and $InfoTtl is a reference that points at an integer used
118475ce41a5SAli Bahrami# to count how many lines have been sent there.
118575ce41a5SAli Bahrami#
118675ce41a5SAli Bahramiif ($opt{E}) {
118775ce41a5SAli Bahrami	open(ERROR, ">$opt{E}") || die "$Prog: open failed: $opt{E}";
118875ce41a5SAli Bahrami	$ErrFH = \*ERROR;
118975ce41a5SAli Bahrami} else {
119075ce41a5SAli Bahrami	$ErrFH = \*STDOUT;
11917c478bd9Sstevel@tonic-gate}
119275ce41a5SAli Bahrami
119375ce41a5SAli Bahramiif ($opt{I}) {
119475ce41a5SAli Bahrami	open(INFO, ">$opt{I}") || die "$Prog: open failed: $opt{I}";
119575ce41a5SAli Bahrami	$InfoFH = \*INFO;
119675ce41a5SAli Bahrami} else {
119775ce41a5SAli Bahrami	$InfoFH = \*STDOUT;
11987c478bd9Sstevel@tonic-gate}
119975ce41a5SAli Bahramimy ($err_dev, $err_ino) = stat($ErrFH);
120075ce41a5SAli Bahramimy ($info_dev, $info_ino) = stat($InfoFH);
120175ce41a5SAli Bahrami$ErrTtl = \$OutCnt1;
120275ce41a5SAli Bahrami$InfoTtl = (($err_dev == $info_dev) && ($err_ino == $info_ino)) ?
120375ce41a5SAli Bahrami    \$OutCnt1 : \$OutCnt2;
120475ce41a5SAli Bahrami
120575ce41a5SAli Bahrami
120675ce41a5SAli Bahrami# If we were given a list of objects in 'find_elf -r' format, then
120775ce41a5SAli Bahrami# process it.
120875ce41a5SAli BahramiProcFindElf($opt{f}) if $opt{f};
120975ce41a5SAli Bahrami
121075ce41a5SAli Bahrami# Process each argument
121175ce41a5SAli Bahramiforeach my $Arg (@ARGV) {
121275ce41a5SAli Bahrami	# Run find_elf to find the files given by $Arg and process them
121375ce41a5SAli Bahrami	ProcFindElf("find_elf -fr $Arg|");
12147c478bd9Sstevel@tonic-gate}
121575ce41a5SAli Bahrami
121675ce41a5SAli Bahrami# Cleanup output files
121775ce41a5SAli Bahramiunlink $Conf64 if $Conf64;
121875ce41a5SAli Bahramiunlink $Conf32 if $Conf32;
121975ce41a5SAli Bahramiclose ERROR if $opt{E};
122075ce41a5SAli Bahramiclose INFO if $opt{I};
122175ce41a5SAli Bahrami
122275ce41a5SAli Bahramiexit 0;
1223